Some of my most visited Stack Overflow answers are on how to use Git!

We all remember how to add, commit, push, but how often to do you rebase, resolve merge conflicts, modify old commits?

Here I’m going to list out all the Git commands I usually look-up! Including any relevant updates, since Git and the way we use Git is always evolving!


Git config for a directory full of repositories

When you have sets of git repositories with different credentials it can be useful to manage shared git configuration across them.

Example directory layout:

├─ orgXYZ
│  ├─ repoA
|  └─ repoB
└─ org123
   ├─ repo1
   └─ repo2

Now, to set git config for “orgXYZ” I create a file in that directory named .gitconfig and edit ~/.gitconfig with:

[includeIf "gitdir:~/code/orgXYZ/"]
    path = ~/code/orgXYZ/.gitconfig

This instructs git to include directory-specific config that can be shared across multiple repos, in my case I often set a committer email address for each org.

Change committer name and email across multiple commits

One machine, multiple GitHub accounts, and whoops you commited as personX to orgY and you need to correct it!

There are a lot of approaches to this problem, this is the command I have used. git filter-branch emits a warning that it shouldn’t be used.. 🤷‍♂️

⚠ This only works on repositories with a single committer, it overwrites ALL commits.

git filter-branch -f --env-filter "
  " HEAD


Push to remote with current branch name

I like to be careful with my pushes, sometimes I have multiple repository with the same name or multiple remotes in one repository, and I want to be sure which remote I am pushing to, and I would rather not type a long generated branch name each time.

git push origin HEAD

This pushes to a branch on origin with the same name as your current branch, this is safer than git push and hoping you set the correct default remote for this branch. Assuming your branch is named “my_branch”, then this command has the same effect as git push origin my_branch.

Combine multiple commits into one

Maybe you want to hide “fix”, “fixed the fix”, “really fixed this time”, or maybe you just noticed your commit messages a exhausted jibberish!

git reset --soft HEAD~3
git commit

This re-stages the last three commits, leaving the local changes there and the relevant files added to Git, allowing you to write a single new commit message covering all changes.


Modify an old commit

Git Rebase, it’s terrifying.

To start a rebase: git rebase --interactive 'abc123ef^'

Git opens an editor and you need to flag the commits to modify, saving & exiting the editor causes git to open the repository at that commit.

Once your changes are made, commit them with git commit --all --amend --no-edit and then git rebase --continue to move on to the next commit flagged for modification, or if you are finished it will take you back to HEAD.

Since each git commit is cryptographically based on the commits preceding it, this process causes all commit ID’s from the rebased commit upwards to be changed. If anyone else is working on this repository they will encounter errors trying to push or pull and will need to git pull -f to forcefully overwrite the discarded history.

If your motivation is to clean up the history, it’s better done in a squash merge.


Push to a remote branch with a different name

This is a weird one, but if you are working in localBranch and want to push to a branch with a different name then this syntax will help.

git push origin localBranch:remoteBranchToBeCreated

You might want this if you plan to continue wokring on localBranch but want to open a merge request at its current state of development. It’s best to keep your local and remote branches in sync though, this approach gets messy quickly!


Move uncommited changes to a new branch

We’ve all forgotten to change branch before making changes before, this command changes to a new branch and brings your uncommitted changes with you.

git switch -c <new-branch>

Prior to Git 2.23 we used git checkout -b <new-branch>. The result is the same, but “switch” is more descriptive and less confusing than the overused “checkout”.

Thanks Move existing, uncommitted work to a new branch in Git

Merge changes from another repository

Let’s say someone forked your project and you want to locally pull their changes into your branch, the following instructions set up the fork’s remote, checks out a local branch based on the forked repository, at which point you can perform your merge.

git remote add fork <url of fork>
git fetch fork <branch>
git checkout -b fork_branch fork/<branch>

This will create the local branch fork_branch with the same history like in the fork, i.e. fork_branch will branch off of your main where does in the fork. Additionally, your local branch will now track that branch in the fork, so you can easily pull in new changes committed in the fork.

Thanks Git pulling a branch from another repository?