Table of Contents

git

Distributed version control from Finland.

Branches

Branches are a way to keep some code separate from other code.

Usually you should adopt a branching model, here is a good example: https://nvie.com/posts/a-successful-git-branching-model/

It isn't a good idea to commit directly to your main branch. You should instead have separate branches for different actions:

Merging

If you want to merge the fix-foo branch into the main branch:
git checkout main && git merge fix-foo
If you don't have diverging history, this will usually result in a fast-forward.

Keep history

When merging branches using the previous model, you should use --no-ff as it keeps the supporting branches history.

To make this the default behaviour, use git config --global merge.ff no along with git config --global pull.ff only to keep git from creating a merge commit when pulling.
To override this, use git merge --ff

Commits

Write good, standardized commits.
Commit title: <type>[optional scope]: <description>

Types: fix, feat, chore, docs, refactor, test
Scopes: the specific component/area you're working on

See https://www.conventionalcommits.org/en/v1.0.0/ for more info.

Checkout old versions

You want to revert a file to a previous commit's state?
git checkout 0a1b2c file.txt

Amend commits

Change the last commit message with git commit --amend. Change its contents as well by running the regular commands and amend as regular.

Search commits

Search through commits with git log <options>
Some useful options:

View changes in commit editor

By default, git shows you which files were modified while writing a commit message in your configured editor. It may be helpful to also see what changed, or the patch set.
You can configure git to do this by default with git config --global commit.verbose true

Verified commits

If you want to use verified commits, you should have a GPG key added to git and your git server account.
To add a GPG key to git, first get your key ID with gpg --list-secret-keys --keyid-format=long, then use git config --global user.signingkey IDHERE
Enable signing for commits and tags with git config --global commit.gpgsign true and git config --global tag.gpgsign true respectively.

To not manually type the GPG key's password every time you commit, you can integrate GPG with a compatible DBus Secret Service API provider, such as KeePassXC.
See https://wiki.archlinux.org/title/GnuPG#pinentry and https://c3pb.de/blog/keepassxc-secrets-service.html for more details.

Reset

You can undo your changes with git reset HEAD~

git reset does three things depending on its paremeters:

  1. Move the branch HEAD points to (--soft)
    • Undo your last commit
  2. Make the index look like HEAD (default)
    • Undo your last commit and unstage everything
  3. Make the working directory look like the index (--hard)
    • Warning: You can lose work forever: git overwrites any changes with the last commit's version.

Remotes

Git remotes

Rebasing

git rebase branch modifies your git history so that two branches are merged into one without a merge commit (the history is now linear, as if there was only one branch)

Split up commits

You can split up commits that are too large by rebasing.
Run git rebase -i HEAD~2 to rebase the last two commits, and change the appropiate's commit command to edit. Uncommit your latest changes (mixed reset) with git reset HEAD^ and start an interactive commit session with git commit -p. This allows you to edit the patch manually, selecting what you need for specific, more self-contained commits.
Git's interactive commit editor has a lot of options (press ? to summarize them) but normally you need to split the commit with s, accept with y and quit with q.

See https://git-scm.com/book/en/v2/Git-Branching-Rebasing and https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History for info on rebasing.
See https://git-rebase.io/ for a guide with examples on rebasing.

Squash multiple commits

If you want to squash multiple commits into one, rebase interactively the last n commits with git rebase -i HEAD~n and squash the commits with s.

Aliases

Git aliases help you run frequent commands faster.
To set an alias, use git config --global alias.<NAME> '<GIT COMMAND>'

Current custom aliases:

Alias Git command Note
graph log –pretty=format:“%h %s” –graph Prints a graph of the commit history
last log -1 HEAD Shows last commit

Searching through code

You can use git grep to search through git trees really fast. You can also search in a tag by adding the tag name at the end.

See https://git-scm.com/book/en/v2/Git-Tools-Searching for more info.

Offline git

A solution would be to use something like a USB stick, make a bare repo on it with git init --bare and add the new repo as a remote for the local repo to be shared with git remote add usbstick /mount/usb/repohere. Push to it with git push usbstick main from your local repo.

See James Gibbard's site for more info: https://www.gibbard.me/using_git_offline/

Learn git

Learn git by reading the git book: https://git-scm.com/book/en/v2
Additional material:

Best practice

https://www.conventionalcommits.org/en/v1.0.0/ → write good commits
https://semver.org/ → version your stuff good
https://man.sr.ht/lists.sr.ht/etiquette.md → sr.ht mailing list etiquette