I use Git every single day.
So do most software developers.
Honestly, Linus Torvalds’ little side project almost feels like a miracle.
However, the tool is so powerful and extensive that it’s easy to get lost in all the possible commands it has.
Hence, based on my own experience, here’s a compilation of answers to common questions about “how do you do X with Git” that I’ve encountered on a regular basis. Some of us may even use these solutions on a daily basis.
Indeed, many of the commands addressed here will be rather simple, and often well-known by the majority of developers.
However, I thought this could be beneficial as a one-stop-shop place for remembering that one command you forgot, as well as providing a good foundation for beginners.
If instead you’d prefer to go over a practical deep dive of Git, you can check out this article.
The Git Cheatsheet 🗒
S️toring changes without committing them
This is a simple one, just run:
Then, to bring back these stored changes, making sure you’re on the same branch, you can run:
git stash apply
Getting rid of all uncommitted changes
Sometimes you want to try something and it just doesn’t work out. To get rid of all changes you made since the last commit, just run:
git checkout -- .
To only erase changes from specific files or directories,
. can be substituted by a list of files and/or directories you wish to erase changes from.
Syncing your fork with the main repo
When you fork a project, it’s important that you keep your fork up-to-date to avoid complicated merge conflicts when you make a pull request, or simply to make sure you have all the new features and security patches.
As such, here’s how you sync your fork:
- Add a remote repository
Get the address of the upstream (main) repo from where you forked the project. Then run the following, substituting the URL:
git remote add upstream <upstream_repo_url>
You can check that this worked by running
git remote -v .
2. Sync the fork with the upstream repo
To sync the fork, fetch the upstream repo:
git fetch upstream
Then, on the branch you wish to sync with (generally
git merge upstream/master
git rebase upstream/master depending on your strategy of choice.
Erase the last X commits
Made some commits that you ended up needing to revert? You can do so in two ways:
git reset HEAD~2 # undo the commits but keep the changesgit reset --hard HEAD~2 # undo the commits and discard changes
With the second option, it will be as if the commits never happened.
You should replace the 2 with the number of commits you wish to go back from the latest commit (HEAD).
Squash various commits into one (without rebase!)
If you want to get rid of all your
"fix typo" commits and join them all together into one, you can do so with:
git reset --soft HEAD~2 && git commit -m "your message"
Remember to replace the 2 with the number of commits you want to squash counting from the HEAD.
Checkout the state of the project at a past commit
To go back in time and see the state of your project at a given commit in the past, first run
git log to see the commit history and select the commit you wish to go back to.
Then, copy its hash and simply run
git checkout <commit_hash> . This will leave you in “detached head” mode. To go back, just
checkout the branch by name.
Ignoring a file you already added to Git
We’ve all been there — adding or committing something we shouldn’t have. To remove the file from Git tracking while keeping it in the system, just do:
git reset <file> && echo <file> >> .gitignore
Adding to a commit after committing
If you want to change your commit message, or add a new file to it, you can use
git ammend .
To change the message, use:
git commit --amend -m "<new_message>"
And to add a new file to the last commit:
git add <file> && git commit --amend
Note that this “saves you the trouble of creating a new commit”, but in fact does create a new commit under the hood. Hence, you should only be doing this if you haven’t pushed the changes to the remote repo yet.
Removing a file from Git and pruning its entire history
If you ever push sensitive data to a remote repository (e.g. on GitHub), you’ll not only need to remove the file from Git tracking, but also delete its entire history.
You should also not use that data anymore if at all possible, such as in the case of API keys, passwords, etc.
The process for doing so isn’t the simplest, but GitHub has written a full-page tutorial about it, so I thought I should just link it here instead.
Record merge conflict resolutions
To avoid having to resolve the same exact merge conflicts multiple times, you can enable a Git cache of merge conflict resolution. This will store how a merge conflict was resolved and automatically resolve the same conflict if it comes up again:
git config --global rerere.enabled true
Read more about this on the Git Docs.
Commits made on the wrong branch
If you made a commit on the wrong branch, you should be able to use our knowledge about erasing commits to solve the problem, like so:
git branch <new_branch> && git reset HEAD~2 --hard
This will create a new branch and delete the specified number of commits from the current branch where you wrongly added the commits.
If you actually want these commits on an existing branch rather than a new one, then you can do:
git checkout <desired_branch> && git merge <branch_with_commits>
git checkout <branch_with_commits> && git reset HEAD~2 --hard
And yet, if merging is not an option, you can use
git cherry-pick , like so:
git checkout <desired_branch>
git cherry-pick <branch_with_commits> <branch_with_commits>~2
git checkout <branch_with_commits> && git reset HEAD~2 --hard
Changing a branch name
To change the name of a branch, use
git branch -m . You can either change the name of the current branch:
git branch -m <new_name>
Or change the name of any branch:
git branch -m <old_name> <new_name>
Finding the commit with a bug
If you run into an issue that you know is unrelated to your commit, you’ll need to determine what commit in the past introduced this problem. This is common with tests, for example, when they aren’t passing due to a test completely unrelated to your work.
In this case, to find the “bad” commit, you can use
git bisect .
The way it works is as follows:
- Start the process
git bisect start
2. Mark the current commit as “bad”
git bisect bad
3. Mark a commit in the past as “good”
Find a commit in the past, using
git log for example, where things were as intended (i.e. good). Then, run:
git bisect good <commit_hash>
4. Get bisecting!
You should now get a message like this:
Bisecting: 2 revisions left to test after this (roughly 3 steps)[6ca4a67aeb4b0d9835ecf15e44505c48f93642c9] my-branch
The numbers, hash, and branch name will naturally be different for you.
Here, what Git is doing is going through your commits one by one, until you find the one which is broken. You don’t need to run
git checkout as that’s being handled for you.
At every commit, you should then check if things are OK. If they aren’t, mark the commit as bad with
git bisect bad . If they are, mark it as good with
git bisect good .
Once you mark a commit as good, Git will take you to the first “bad” commit (i.e. the last one you marked as bad) so you can properly investigate the error. Once you’re done, just go back to the HEAD of the branch by checking the branch out (
git checkout <branch> ) and fix the issues.
This is it from me today. Git is an awesome tool and I hope this cheatsheet helps you with some of the problems you may encounter along the way.
It definitely does not cover everything you need to know, but it’s a good start.
Thanks for reading and let me know about your favorite Git commands in response to this article.