Introduction

The following is a dump of Git commands for use on your shell of choice.

This book is generated with mdBook and hosted by GitLab Pages.

The book can be served locally by running mdbook serve.

History

In mid-2014 I started a GitHub Gist with the commands to work with Git (having moved from TFS and Subversion before that). As that Gist grew it became rather unwieldly, so I looked for something better, where I could continue to create Markdown files with the various commands that I found helpful as I learned Git.

In 2018 GitBook was a great choice, but in 2019 they changed their business model and mdBook was there to seamlessly fill the gap. Thankfully GitLab Pages continues to be a great resource for hosting this material.

Even if no one else uses it, I regularly find a need to come back to, and expand, this book, as there's just some commands that I need to look up. But I hope I'm not the only one that reads these words and gets some benefit from them.

Comments and suggestions welcome, especially if you have some cool logging formats you'd like to share. Git repo linked above and on the top right of each page.

Notes and warnings

If you want to escape, typically Shift + Q is the way to do so on Windows. This includes after running a command like git log (depending upon what it uses; Q will exit if it's using less for paging).

Also on Windows, remember that you can use notepad <filename> to open/create a file in Notepad.

Getting started

# Clone a repository into a new directory in the current directory.
git clone _.git
git clone _.git differentFolderName

# Create a new repository in the current directory.
git init
# Add a new remote for a repo. In this case 'upstream' might be helpful for the repo this was forked from.
git remote add upstream _.git

# Create a new branch.
git branch <branchName>

# Switch current repo to a different, existing, branch.
git checkout <branchName>
git checkout master

Clone troubleshooting

# If running into issues cloning a repository, clones a shallow copy. Then updates remotes and fetches everything.
git clone --depth=1 _.git
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch --unshallow

Getting started on macOS

Use Homebrew.

Install Git

brew install git

Update Git

If you haven't updated brew in a while, you can both make sure it and all applications are current.

brew update && brew upgrade

Otherwise just upgrade Git itself:

brew upgrade git

Getting started on Windows

There's a lot of different options. In no particular order:

Configuration

The following sections covers general configuration and information.

User information

# Pull user information.
git config user.name
git config user.email

# Update all repository user name.
git config --global user.name "Your Name"

# Update individual repository user name / email.
git config user.name "Your Name"
git config user.email "[email protected]"

Git configuration

# See where configuration options are set.
git config --list --show-origin
git config --list --show-origin --name-only
git config --list --show-origin --show-scope --name-only

# Edit system/global/local.
git config --system --edit

Defaults

# Set the default branch name when using git init. Here set to 'main'.
git config --global init.defaultBranch main

Repository information

Configuration

# List config details, including remotes, for the current repo.
git config --local -l

# List all configuration settings for the current repository, including global and system.
git config -l

Remotes

# Change remote origin URL (repo name change or move).
git remote set-url origin _.git

# See what remotes are setup on a repo.
git remote -v

# See more information about remotes (origin in this case).
git remote show origin

# Add a new remote with name _ and location _.git.
git remote add _ _.git

# Rename a remote.
git remote rename old-name new-name

# Delete a named remote.
git remote rm _

# Delete the origins push URL.
# May be necessary for projects that explicitly set a fetch and push URL.
git remote set-url --delete --push origin push.git

Branches

# List all local branches.
git branch --list

# List all branches, including remotes.
git branch -a

# List all branches merged into master (for cleanup).
git branch --merged

Size

# List database information, include size (size-pack = kb).
git count-objects -v

# Runs database clean-up.
git gc

# Check validity of objects in the database.
# File System Check
git fsck

Beyond Compare

If you use Beyond Compare, the following sets up Git to use it for diff and merge.

git config --global diff.tool bc
git config --global difftool.bc.path "c:/Program Files/Beyond Compare 4/bcomp.exe"
git config --global merge.tool bc
git config --global mergetool.bc.path "c:/Program Files/Beyond Compare 4/bcomp.exe"
# This is up to the user on whether they want to keep .orig files.
git config --global mergetool.keepBackup false

Included Tools

# Simple GUI for Git.
git gui
# Simple GUI showing current branch commits.
gitk
# Simple GUI showing all branches and commits.
gitk --all

Commits

# Use a basic GUI. Actually works quite well for staging hunks that can't be split.
git gui

Viewing changes

# See what has changed/etcetera
git status

# See only changes to tracked files
git status -uno
git status --untracked-files=no

# See which files have changed.
git diff --stat

# See how many files have changed (insertions/deletions). Linux/macOS.
git diff --stat | tail -n1

# See what or how many files are staged.
git diff --cached --stat
git diff --cached --stat | tail -n1

# See differences, with words colored inline.
git diff --color-words

# Difference. Use Shift + Q to quit. (Q may also work.)
git diff <file>

# Difference, ignoring space changes (EOL and multiple into one).
git diff -b <file>

# See what changed in a file that's already been staged.
git diff --cached <file>

Staging changes

# Add/stage a new/updated file.
git add <file>

# Add/stage multiple files, space delimited
git add <file> <file>

# Add a file with prompts on what to do with hunks
git add <file> -p
git add <file> --patch

# Add/stage all changes with prompts on what to do with hunks.
git add -p

# Add/stage all changes (including deletions)
git add -u

# Work in Interactive mode.
git add -i

# Add/stage file deletion.
git rm <file>

# Add/stage file move/rename (such as case sensitive change)
git mv -f <file> <File>

# Add/stage directory rename.
git mv <oldDirectoryName> <newDirectoryName>

Reverting local changes

# Unstage change.
git reset HEAD <file>
git restore --staged <file>

# Unstage all changes.
git reset

# Selectively unstage changes to files.
git reset -p

# Discard changes to a file
git checkout -- <file>

# Selectively discard changes to a file
git checkout -p

# Discard all local changes to tracked files. Leaves new files/folders as-is. Helpful if you did a mass find/replace and want to undo it.
git checkout -f
git checkout --force

# Discard all untracked files, interactively.
git clean -i

# Get a file from a particular commit.
git checkout a1b2c3 -- <file>

# Get a file from the commit previous to the commit. Helpful if you want to revert a change just made to a file.
git checkout a1b2c3~1 -- <file>

Commit changes

# Commit with Message.
git commit -m "Message"

# Commit with a summary and detail. Additional -m parameters can be passed as needed.
git commit -m "Summary" -m "Details."
git commit -m "Summary" -m "Details." -m "Another line/paragraph of details."

# Add all changed files and commit. New files are not committed.
git commit -am "Message"

More commit viewing

# Show changes made in a particular commit.
git show <commit_id>

# Show changes made in last commit.
git show HEAD

# Show the message and files from a particular commit.
git show --stat <commit_id>

# See a list of changes made in branchName2 not in branchName1.
git diff <branchName1>...<branchName2>

# See a list of files that have changed in the current branch, compared to master. Includes number of files and inserts/deletes.
git diff --stat master...
git diff --stat master...<branchName>

# See the number of changed files, and how many inserts/deletes there were in a branch, since master.
git diff --shortstat master...<branchName>

# See a list of just the file names that were changed in a branch, since master.
git diff --name-status master...<branchName>

Fixing commits

# Update the last commit's message.
git commit --amend -m "Message"

# Update the last commit's date (reflected on GitHub).
git commit --amend --no-edit --date="Fri Nov 6 20:00:00 2016 -0600"

# Add another file to the last commit. Uses the last message.
git add <file>
git commit --amend -C HEAD

# Revert the last commit.
git revert HEAD

# Revert only the second to last commit. Etcetera
git revert HEAD~1

# Revert the last three commits, but stage the reversion locally.
git revert --no-commit HEAD~3..

# Reset working files to match master (or another branch), removing local changes and commits.
git fetch --all
git reset --hard origin/<branchName>

Stashing changes

# Stash changes in tracked files.
git stash

# Also stash untracked changes.
git stash -u

# List all stashes.
git stash list

# View all stashes in a pretty list.
git stash list --pretty=format:'%Cblue%gd%Cred: %C(yellow)%s'

# View changes in all stashes.
git stash list -p
# Pipe into VS Code.
git stash list -p | code -

# Show file changes in a particular stash (0 = last one).
git stash show '[email protected]{0}'

# Show individual changes in a particular stash.
git stash show -p '[email protected]{0}'

# Show stashed changes in individual file.
git diff ..stash -- <file>

# Create a patch file from the above.
git diff ..stash -- <file> > name.patch

# Apply stashed changes in an individual file.
git diff ..stash -- <file> | git apply

# Apply changes from the last stash. Keep the stash.
git stash apply
git stash apply '[email protected]{0}'

# Apply changes from the last stash. Drop the stash after.
# git stash pop = git stash apply && git stash drop
git stash pop

# Drop the most recent stash.
git stash drop
git stash drop '[email protected]{0}'
git stash drop 0

# Drop a particular stash.
git stash drop '[email protected]{2}'

Using a temporary stash to pull/merge

# If you can't pull/merge due to a file conflict, create a temporary stash.
git stash
# Pull changes.
git pull
# Apply and drop the stash.
git stash pop

Collaboration

# Pull from default remote.
git pull

# Push to default remote.
git push

# Push to 'origin' remote from 'master' branch.
git push origin master

# Sync with the repo this was forked from / the remote associated with 'upstream.'
git pull upstream master

# Fetch from all remotes, by default, unless remotes are setup in the config.
git remote update

Branching

# Create a new branch.
git branch <branchName>

# Create a new branch at a specific commit, and switch to it.
git checkout -b <branchName> 3f4308df1e0b7f663d851108128e8e53deb1b5fb

# Switch to an existing branch.
git checkout <branchName>
git checkout master

# Switch to the previous branch.
git switch -
git switch @{-1}
# For use in PowerShell.
git switch '@{-1}'
git checkout -
git checkout @{-1}

# Checkout and switch to a new branch.
git checkout -b my_new_branch

# Push the new branch to a remote.
git push -u origin my_new_branch

# Alternative way to push a branch to a remote, without permanently setting the upstream.
git push origin my_new_branch

# Checkout a remote branch.
git checkout --track origin/<branchName>

# Merge changes from master into a branch.
git checkout <branchName>
git merge master

# Abort a merge (such as if there's conflicts that need to be resolved differently).
git merge --abort

# Delete a branch.
git branch -d my_new_branch

# Delete a branch on the remote.
git push origin :my_new_branch

# Merge two local branches, without fast-forwarding, with default editor opening to modify the message.
git merge <branchName> --no-ff --edit

# Merge two local branches, without fast-forwarding, and including messages for the last X (20 here) commits.
# According to Linus Torvalds, the better way to do merges.
git merge <branchName> --log=20 --no-ff

# While on a different branch, update the master branch from remote.
# See https://stackoverflow.com/a/42902058/11912
git fetch origin master:master

# Put recent local commits in master into a new branch.
# X is the number of commits to rollback.
git branch <branchName>
git reset --hard HEAD~X
git checkout <branchName>

# Add a specific commit on top of the current branch.
git cherry-pick <commit-id>

# Add a specific commit on top of the current branch, but don't automatically commit it. Allows you to manually tweak what's getting pulled in.
git cherry-pick -n <commitId>

# Rename the current branch
git branch -m <newBranchName>

# Get the name of the previous branch.
git rev-parse --symbolic-full-name @{-1}
# For PowerShell.
git rev-parse --symbolic-full-name '@{-1}'

Management

# Show all current branches, including remotes.
git show-branch -a --list

# Show all local branches that have been merged into master.
git branch --merged

# Show all local branches that have not been merged into master.
git branch --no-merged

# Show all local branches, sorted by and showing last commit
# https://stackoverflow.com/a/5188364/11912
git for-each-ref --sort=committerdate refs/heads/ --format='%(HEAD) %(color:yellow)%(refname:short)%(color:reset) - %(color:red)%(objectname:short)%(color:reset) - %(contents:subject) - %(authorname) (%(color:green)%(committerdate:relative)%(color:reset))'

# Do a dry run of pruning local branches that no longer exist on a remote.
git remote prune origin --dry-run

Worktree

# List all worktrees for the current repo.
git worktree list

# Create a new worktree for a specific branch. Path can't be a current working directory.
git worktree add ../path/for/branchName

# Delete a worktree.
git worktree remove path/to/worktree

Rebasing

git rebase in the Atlassian Git Tutorial has a nice overview of this command.

# Rebase the current branch by appying them to the passed branch.
git rebase <branchName>

Tags

# List all tags.
git tag

# Create a new tag, locally.
git tag -a TagName -m "Message"

# Delete a tag.
git tag -d TagName

# Push a tag to a remote (local by default).
git push origin TagName

Logging

# View the commit log, in various ways.
git log
git log --oneline
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset'
git log --graph --date=short --pretty=format:'%C(yellow)%h%C(reset) %C(green)%ad%C(reset) %C(red)|%C(reset) %s %C(bold blue)[%an]%C(reset)%C(yellow)%d%C(reset)'
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen%cn%Creset %Cblue(%cr)%Creset' --abbrev-commit --date=relative
git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
git log --graph --pretty=format:'%C(auto)%h%Creset - %d%s %Cgreen(%cr) %C(bold magenta)<%an>%Creset'
git log --decorate --graph --abbrev-commit --date=relative
git log --graph --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset'

# View the last commit's message and changed files.
git log -1 HEAD --stat

# View commits that touched a file.
git log --full-history -- <file>

# View commits that touched a directory.
git log --full-history -- *\<directory-name>\*

# View commits that touched a directory.
git log <directory-path>
git log --pretty=oneline <directory-path>
git log --stat <directory-path>

# View last X commits, with message and files, that touched a directory.
git log --stat -X <directory-path>
git log --name-status -X .

# View commits that touched a file.
git log -p <file>

# View commits that touched a file, including renames.
git log --follow -p <file>

# View commits that have deleted files.
git log --diff-filter=D --summary

# View all deleted files.
git log --all --pretty=format: --name-only --diff-filter=D | sort -u

# Search commits messages for specific text (case sensitive).
git log --grep="searchTerm"

# Search commit diffs for changes in count of text (added or removed).
git log -SsearchTerm
git log -SsearchTerm -i

# Search commit diffs for specific text (case sensitive) showing changed lines.
git log -SsearchTerm -p

# Search commit diffs for changes involving search term.
# You can type /searchTerm to use the pager to find the first instance, and then n to find the next one(s).
git log -GsearchTerm -p

# Search commit contents for specific text.
git grep "searchTerm"
git grep -i "searchTerm"

# View all commits that are in branch-2 that are not in branch-1.
git log branch-1..branch-2

# View all commits ending with a particular branch
git log <branchName> --graph
git log <branchName> --graph --oneline

# View all commits merging a branch into master
git log --merges --first-parent --format=oneline

# View where all branches are in the commit history.
git log --color --graph --oneline --decorate --simplify-by-decoration --all

# View all users who committed to the repository, ordered by number of commits
git shortlog -s -n

# View mostly commonly modified files, based upon commits.
git log --pretty=format: --name-only | sort | uniq -c | sort -rg | head -10

# View all files in Git with the date the file was last touched in Git.

# macOs.
git ls-files | while read file; do git log -n 1 --pretty="Filename: $file, commit: %h, date: %ad" -- $file; done | less

# PowerShell.
git ls-tree -r --name-only HEAD | ForEach-Object { "$(git log -1 --format="%ai" -- "$_")`t$_" }

Log output examples

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' Example 1

git log --graph --date=short --pretty=format:'%C(yellow)%h%C(reset) %C(green)%ad%C(reset) %C(red)|%C(reset) %s %C(bold blue)[%an]%C(reset)%C(yellow)%d%C(reset)' Example 2

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen%cn%Creset %Cblue(%cr)%Creset' --abbrev-commit --date=relative Example 3

git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit Example 4

git log --graph --pretty=format:'%C(auto)%h%Creset - %d%s %Cgreen(%cr) %C(bold magenta)<%an>%Creset' Example 5

git log --decorate --graph --abbrev-commit --date=relative Example 6

git log --graph --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s %C(white)- %an, %ar%Creset' Example 7

Aliases

These log formats are ones that I've used quite a bit in the past, so I've set these as Aliases.

lg1

git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)' --all Example lg1

lg2

git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset) %C(dim white)- %an%C(reset)' --all Example lg2

lg3

git log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(bold yellow)%d%C(reset)%n'' %C(white)%s%C(reset)%n'' %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)' --all Example lg3

Files

ls-files

# List files in Git.
git ls-files
git ls-files -c
# List modified files.
git ls-files -m
# List other (untracked, ignored, ...) files.
git ls-files -o
git ls-files --others

# List directories other files are in.
git ls-files -o --directory
# List untracked ignored files, based upon .gitignore.
git ls-files -io --exclude-from=.gitignore

cat-file

# Pretty-print the contents of HEAD.
git cat-file -p HEAD
# Pretty-print the contents of a tree ID (file list), for example the tree ID from -p HEAD.
git cat-file -p <id_from_tree>
# Pretty-print the contents of an ID, for example the parent ID from -p HEAD.
git cat-file -p <id_from_parent>

Example: Updating a fork

# On the fork:
git checkout master

git pull upstream master

git push origin master

# If the branch should be created.
git checkout -b new_branch
git push -u origin new_branch

# If the branch already exists.
git checkout branch_name
git merge master

# If there are conflicts:
# Uses the default merge tool against all conflicts, one at a time.
git mergetool
# Uses the default merge commit message.
git commit --no-edit

Example: Create a new repo from a subdirectory

Useful if you want to pull a directory, and its commit history, out into a new repo.

# Clone the repository into a new directory.
git clone _.git

# Get only the files and commits impacting a particular directory.
# This should be the name of the directory only; if using PowerShell or the like make sure it does not include path information.
# <branchName> is the name of the default branch, generally master.
git filter-branch --prune-empty --subdirectory-filter <pathToDirectory> <branchName>

# View and then update your remotes with the new repo location.
git remote -v
git remote set-url origin _.git

git push -u origin <branchName>

Aliases

The following are some aliases that I have setup.

Find them by running the following

git config --get-regexp 'alias.*'
# Define an alias to change user information for a repo.
git config --global alias.workprofile 'config user.email "[email protected]"'
# With the above alias defined, run in a repo directory to switch user information for the specific repo.
git workprofile

Logging

git config --global alias.last 'log -1 HEAD --stat'
git config --global alias.lg "!git lg1"
git config --global alias.lg1 "!git lg1-specific --all"
git config --global alias.lg2 "!git lg2-specific --all"
git config --global alias.lg3 "!git lg3-specific --all"
git config --global alias.lg1-specific "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(bold yellow)%d%C(reset)'"
git config --global alias.lg2-specific "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(bold yellow)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'"
git config --global alias.lg3-specific "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset) %C(bold cyan)(committed: %cD)%C(reset) %C(bold yellow)%d%C(reset)%n''          %C(white)%s%C(reset)%n''          %C(dim white)- %an <%ae> %C(reset) %C(dim white)(committer: %cn <%ce>)%C(reset)'"

Self-hosting with Gitea

Vultr Gitea instance with PostgreSQL

The following is example configuration for a low-cost Vultr instance that can easily run Gitea with PostgreSQL used for data storage.

  1. Cloud Compute
  2. intel Regular Performance
  3. Chicago United States
  4. Debian 11 x64
  5. 25 GB SSD for $5/month with 1 vCPU, 1 GB Memory, 1 TB Bandwidth
  6. Disable Auto Backups
  7. Enable IPv6

Initial setups

  1. Create a new non-root user
    • adduser <new-user>
    • usermod -aG sudo <new-user>
    • exit
  2. Initial updates
    1. sudo apt update
    2. sudo apt upgrade if needed (wasn't required)
    3. sudo apt autoremove to remove ~310 MB of packages
  3. Install required packages
    1. sudo apt install postgresql (version 13)
    2. sudo apt install git (version 2.30.2)
    3. sudo systemctl start postgresql
    4. sudo systemctl enable postgresql
    5. sudo systemctl status postgresql

PostgreSQL Setup

  1. sudo vim /etc/postgresql/13/main/postgresql.conf
    • Under Connections and Authentication, update password_encryption from md5 to scram-sha-256 and uncomment.
  2. sudo vim /etc/postgresql/13/main/pg_hba.conf
    • Update all md5 instances to scram-sha-256.
  3. sudo service postgresql restart (restart service / reload config)
  4. sudo -i -u postgres
  5. psql
  6. CREATE ROLE gitea WITH LOGIN PASSWORD 'TODO-SET-PASSWORD';
    • Alter it: ALTER ROLE gitea WITH PASSWORD 'TODO-SET-NEW-PASSWORD';
  7. CREATE DATABASE giteadb WITH OWNER gitea TEMPLATE template0 ENCODING UTF8 LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8';
  8. quit (psql)
  9. exit (postgres user)
  10. sudo vim /etc/postgresql/13/main/pg_hba.conf
    • Add a new line with local giteadb gitea scram-sha-256 for local access.
  11. sudo service postgresql restart
  12. psql -U gitea -d giteadb to verify access.

Install Gitea (1.16.8 at the time of writing)

  1. uname -mrs to confirm amd64.
  2. Get link from https://dl.gitea.io/gitea/
    • https://dl.gitea.io/gitea/1.16.8/gitea-1.16.8-linux-amd64
  3. wget -O gitea https://dl.gitea.io/gitea/1.16.8/gitea-1.16.8-linux-amd64
  4. chmod +x gitea
  5. sudo mv gitea /usr/local/bin/gitea
  6. sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git
  7. Setup directory structure:
    • sudo mkdir -p /var/lib/gitea/{custom,data,log}
    • sudo chown -R git:git /var/lib/gitea/
    • sudo chmod -R 750 /var/lib/gitea/
    • sudo mkdir /etc/gitea
    • sudo chown root:git /etc/gitea
    • sudo chmod 770 /etc/gitea
  8. sudo wget https://raw.githubusercontent.com/go-gitea/gitea/main/contrib/systemd/gitea.service -P /etc/systemd/system/
  9. sudo nano /etc/systemd/system/gitea.service
    • Uncomment Wants=postgresql.service and After=postgresql.service lines.
  10. sudo systemctl daemon-reload
  11. sudo systemctl enable --now gitea
  12. sudo systemctl status gitea
  13. sudo ufw allow 3000/tcp

Configure Gitea

  1. http://:3000
  2. Select PostgreSQL as Database Type
  3. Set Password.
  4. Change Database Name to giteadb
  5. Update Gitea Base URL to http://:3000/
  6. Create a new administrator account.
  7. Once setup, logout and log back in with new account.
  8. sudo vim /etc/gitea/app.ini if you want to update after the fact.

Lockdown Gitea

This locks down Gitea so that only signed in users can access the site, and registration isn't available.

  1. sudo vim /etc/gitea/app.ini
  2. [service]
    • DISABLE_REGISTRATION = true
    • REQUIRE_SIGNIN_VIEW = true
  3. sudo service gitea restart
  4. sudo chmod 750 /etc/gitea
  5. sudo chmod 640 /etc/gitea/app.ini

Nginx

  1. Setup a new (sub)domain to point to the server.
  2. Should be able to access http://:3000.
  3. sudo apt install nginx
  4. sudo ufw allow 'Nginx HTTP'
  5. sudo ufw status
  6. systemctl status nginx
  7. sudo nano /etc/nginx/nginx.conf
server {
    listen 80;
    server_name git.example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
  1. sudo nginx -t to verify configuration changes
  2. sudo systemctl restart nginx
  3. Custom domain, port 80, should now work.

Certbot / SSL

  1. sudo apt install certbot python3-certbot-nginx
  2. sudo ufw allow 'Nginx Full'
  3. sudo ufw delete allow 'Nginx HTTP'
  4. sudo ufw status
  5. sudo certbot --nginx -d git.ebacher-skemp.com (or whatever custom domain was setup)
  6. sudo systemctl status certbot.timer (verify Certbot will run again automatically)
  7. sudo certbot renew --dry-run (fake a cert renewal to make sure it picks it up)
  8. https:// should work for Gitea access, and http should redirect
  9. sudo nano /etc/gitea/app.ini
    • Update server > ROOT_URL
    • Also needed to add a repository > DEFAULT_BRANCH = main
  10. sudo service gitea restart
  11. sudo ufw delete allow 3000/tcp (no longer allow external access via 3000)

Other Customizations

  • In my.vultr.com, add the following tags to the server instance (so I know core functionality):
    • gitea
    • postgresql
    • nginx
    • certbot
  • sudo apt install htop (prettier top)
  • sudo vim /etc/gitea/app.ini
    • repository > ENABLE_PUSH_CREATE_USER = true
    • repository > ENABLE_PUSH_CREATE_ORG = true
    • cron.repo_health_check > TIMEOUT = 90s
  • sudo nano /etc/nginx/nginx.conf
    • Add client_max_body_size 100M; to gitea server section (to allow for larger files)
    • sudo nginx -t
    • sudo systemctl restart nginx

Update Gitea

See https://docs.gitea.io/en-us/install-from-binary/#updating-to-a-new-version for more information.

Create a backup

  1. sudo systemctl stop gitea
  2. sudo su - git
  3. gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -t /tmp
  4. ls -l --block-size=M
  5. exit

Update 1.16.8 to 1.16.9

  1. VERSION=1.16.9
  2. sudo wget -O gitea https://dl.gitea.io/gitea/${VERSION}/gitea-${VERSION}-linux-amd64
  3. sudo systemctl status gitea
    • Stop if needed/didn't backup.
  4. sudo mv gitea /usr/local/bin/gitea
  5. sudo chmod +x /usr/local/bin/gitea
  6. sudo systemctl restart gitea
  7. sudo systemctl status gitea
  8. After some period of time, delete the backup file.

Updating 1.16.9 to 1.17.1

  1. sudo systemctl stop gitea
  2. sudo su - git
  3. gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -t /tmp
  4. ls -l --block-size=M
    • rm <old-backup-file>
  5. exit
  6. VERSION=1.17.1
  7. sudo wget -O gitea https://dl.gitea.io/gitea/${VERSION}/gitea-${VERSION}-linux-amd64
  8. sudo systemctl status gitea
  9. sudo mv gitea /usr/local/bin/gitea
  10. sudo chmod +x /usr/local/bin/gitea
  11. sudo systemctl restart gitea
  12. sudo systemctl status gitea
  13. After some period of time, delete the backup file.

Updating 1.17.1 to 1.17.2

  1. sudo systemctl stop gitea
  2. sudo su - git
  3. gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -t /tmp
  4. ls -l --block-size=M
    • rm <old-backup-file>
  5. exit
  6. VERSION=1.17.2
  7. sudo wget -O gitea https://dl.gitea.io/gitea/${VERSION}/gitea-${VERSION}-linux-amd64
  8. sudo systemctl status gitea
    • Should be inactive/dead.
  9. sudo mv gitea /usr/local/bin/gitea
  10. sudo chmod +x /usr/local/bin/gitea
  11. sudo systemctl restart gitea
  12. sudo systemctl status gitea
    • Should be active (running).
  13. After some period of time, delete the backup file.

Updating 1.17.2 to 1.17.3

  1. sudo systemctl stop gitea
  2. sudo su - git
  3. gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -t /tmp
  4. ls -l --block-size=M
    • rm <old-backup-file>
  5. exit
  6. VERSION=1.17.3
  7. sudo wget -O gitea https://dl.gitea.io/gitea/${VERSION}/gitea-${VERSION}-linux-amd64
  8. sudo systemctl status gitea
    • Should be inactive/dead.
  9. sudo mv gitea /usr/local/bin/gitea
  10. sudo chmod +x /usr/local/bin/gitea
  11. sudo systemctl restart gitea
  12. sudo systemctl status gitea
    • Should be active (running).
  13. After some period of time, delete the backup file.

Gitea LFS config also updated:

  1. sudo vim /etc/gitea/app.ini
  2. Move server.LFS_CONTENT_PATH to a new lfs.PATH (/var/lib/gitea/data/lfs).
  3. sudo systemctl restart gitea
  4. sudo systemctl status gitea

Regular backups

On the server:

sudo systemctl stop gitea
sudo su - git
gitea dump -c /etc/gitea/app.ini -w /var/lib/gitea -t /tmp
ls -l --block-size=M
rm <old-backup-file>
# Grant everyone read access to the backup file.
chmod a=r <backup-file>
exit
sudo systemctl restart gitea

On your local machine:

# Copy the file locally.
scp <user>@<remote_ip>:/home/git/<backup-file> d:\

Related Links