Skip to content

Working with Git

Tarik Viehmann edited this page Oct 29, 2024 · 3 revisions

Git Setup

  1. Configure your git name and mail (e.g., "John Doe" and "[email protected]" (via git config --global user.name and git config --global user.email) The mail address should also be known to github. If you already have commits with a wrong author or email, the following script may be useful for you to fix your commit history: https://gist.github.com/morxa/c021d192dc077556ada76960d7b481ab
  2. Generate an SSH key on your workstation and register it with your github account.
    1. Set up your preferred editor when handling git. E.g., if you want to use vim:
git config --global core.editor "vim"

Branches

Branch names follow a simple structure of <scope>/<branch-name>, where <scope> is typically your abbreviated name in lower-case (first letter of your name followed by your surname, e.g., jdoe for John Doe) or common in case you plan to collaborate with others in a branch.

We typically do only merge in main development branches (e.g., master) and utilize git rebase (see also here) to update feature branches if needed.

Commit Messages

Commit messages follow a 80 character line limit. Additionally, the first line is expected to be a short description of the form <prefix>:<description>, where <prefix>typically is the name of the component you are working on. When in doubt about the correct prefix, simply check other commits that changed the files you are working on (e.g., using git blame).

Handling Remotes for Repositories

When cloning a repository, you typically need to decide whether you clone it using it's https or ssh address. Typically, cloning using https addresses is used for repositories, which you use without actively working on them (e.g., not pushing changes), while ssh addresses are used if you actively work on the project in question. By using the ssh remote address git will offer your ssh key to the repository host (e.g., github) to authenticate.

If you are unsure what remotes your already cloned repository has, use the following command to display all remotes:

git remote -v

you can change a remote address using:

git remote set-url origin <new-address>

Useful Commands

This section assumes that you already have some basic knowledge about how to create a branch, add commits and push the changes to upstream.

Committing without Checks

We typically make heavy use of pre-commit hooks that do automatic checks and force you to structure your changes properly.

If you ever need to circumvent these hooks, adding the --no-verify option does exactly this, when committing:

git commit --no-verify

Granular way of staging/unstaging/deleting local changes:

git add/reset/checkout -p

Fixing issues in last commit

git add -p
git commit --amend

Fixing issues in older commit (creates a special commit that can be squashed later):

git log
git commit --fixup=<commit-hash-where-changes-belong>

Rewriting commit history (reword commit messages, drop or re-order commits, squash multiple commits together, change of base branch):

git rebase -i <head-to-place-commit-to>

In the simplest case, is likely your remote of the main project branch, e.g., origin/master. Note that rewriting history that is already pushed to the upstream means that your local branch diverges from it. Hence, in order to push the rewritten history, git push -f is needed. This has the potential to cause irreversible data loss, hence you should make sure everything is fine, e.g., by comparing your local branch against it's origin before force pushing:

git diff origin/<your-branch-name>

Updating a local branch that has diverged:

Typically, if you suddenly are in a diverged state, e.g., if git status shows something like

On branch common/current
Your branch and 'origin/common/current' have diverged,
and have 2 and 4 different commits each, respectively.

Then you should try to figure out what the reason for the diverged state is (typically a rebase that was force pushed). It is probably a good idea to check for differences for that:

git diff origin/common/currrent

Typical ways to resolve this situation are:

  1. If the upstream branch misses changes, rebase your local version onto the origin:
git rebase -i origin/<current-branch-name>
  1. If there is nothing missing in origin, you probably want to hard reset your local branch to it's upstream. This deletes all local commits made in your branch, as well as all local changes to tracked files:
git reset --hard origin/<current-branch-name>
  1. If the upsteram is wrong and your local version is right (rarely the case, you should be 100% sure on this), override the origin with your local version:
git push -f

Squashing fixup commits:

git rebase -i --autosquash origin/<base-branch>

where <base-branch> is the branch the current branch is based on (typically master or main)

Dealing with Detached HEAD

This happens if you check out a revision that is not a branch. Typical instances include checking out an origin branch instead of a local one (e.g., git checkout origin/jdoe/bug-fix when it should be git checkout jdoe/bug-fix; checking out a tag (e.g., git checkout v1.0); checking out a commit hash (git checkout de12345b1f); being in the middle of a merge or rebase operation). The solution depends on the reason you are in the detached state, but typical solutions include

  • switching to a local branch
  • creating a new branch from the detached HEAD
  • continuing a rebase or merge by fixing conflicts or aborting a rebsae or merge
  • keeping the HEAD detached, .e.g., if you want to stay at the current revision and do not plan on modifying it.

Reverting local git operations:

git reflog
git reset HEAD@{<head-number-you-want-to-go-back-to>}