My git cheatsheet
Here, I’ll just collect a list of my commonly used commands in git for later reference. I followed along using this excellent branching tutorial.
Other cheat sheets
- Websites:
-
The first website anyone wanting to learn git should visit
-
http://learngitbranching.js.org
An insanely well done tutorial. You can type git commands and see their effects visualized on a beautiful revision graph in real-time.
Use http://learngitbranching.js.org/?NODEMO for a simplified but insanely instructive visualized sandbox of a distributed git repository
-
http://www.drdobbs.com/tools/three-way-merging-a-look-under-the-hood/240164902
The blog post that made me understand three-way merges, and how and when merge conflicts arise.
-
https://git-scm.com/about/distributed
A visualization of three different SCM workflows possible with git
-
http://www.git-tower.com/learn/git/faq
After you understand the basics of git, this FAQ is a nice help for common problems.
-
http://eagain.net/articles/git-for-computer-scientists/
I like to understand concepts on a deep level, so this website (along with the next link below) was very helpful for me. The quote that made it click for me was that a git repository is just a DAG and post-its.
-
http://newartisans.com/2008/04/git-from-the-bottom-up
The PDF linked to on this site is highly recommended on StackOverflow. It shows you git from the inside out (starting at the blob), which enables you to grasp and appreciate git commands on a deeper level.
After reading this, you will understand branches more intuitively. The document teaches you how a git repository is organized internally (surprisingly simple!) and how more complicated commands are just terminology.
-
http://sethrobertson.github.io/GitBestPractices
A very nice collection of how to work with git in real world projects
-
http://nvie.com/posts/a-successful-git-branching-model
The figure in this post finally made me grasp the power of git branches
-
Misc other helpful resources:
- The Pro Git book
- Rewriting history
- Troubleshooting:
- http://ohshitgit.com/ is a kind of FAQ for when you’ve screwed up.
Create a repository
Create a local repository called sandbox
:
Commits
Log
Diff
Branching
We now want to change the code to use variables instead of repeat the “bottles of beer” strings. For that we open up a branch:
Advanced branching
- Set the master branch three commits back (
-f
: even if it exists already)
Merging
Now, as soon as others review and sign off your code, you can merge variable-names into master:
This creates a merge commit.
Watch out for the order of the branch names: here, you merge variable-names into master, so that master contains the commits from variable-names. You could in theory now checkout bugfix and merge master; then, both branches would point to the same merge commit.
This website offers helpful additional info on updating your local repo.
Rebasing
- Rebasing transforms branches into a nice linear sequence of commits
- In short, it changes the base commit of the branch it’s run from
- The danger is that it rewrites history, so you shouldn’t use it if others already pulled the commits you want to rebase
To apply the changes that happened in the master branch to the bugFix branch, you checkout bugFix and then rebase master into bugFix:
In plain words, git rebase master
means rebase the current HEAD on top of master. After this rebase, bugFix is right on top of master (one commit ahead).
To get master up to date with bugFix, you’d have to checkout and rebase master, too.
If you specify two branches, you will rebase master into bugFix as well. This way, you don’t have to be on bugFix when you issue the rebase command:
Interactive rebasing
When you don’t know what commits of your bugFix branch you want to keep, you can review them before you rebase. Again, you check out the bugFix branch, then rebase master into it, but this time, interactively:
If your master branch is up-to-date with the newest commit, you can reorder the last 4 commits via
Moving around in the commit history
- HEAD points to the most recent commit your working is based on
- If you
git checkout
a commit instead of a branch, git detaches the HEAD i.e. it’s notHEAD => master => afbe194
anymore, butHEAD => afbe194
- Instead of a SHA1 hash, you can move upwards with the shortcuts
^
and~<num>
. - You can use the
@{<num>}
syntax along withgit reflog
to see where your HEAD last pointed to.
Reversing changes
An important distinction:
git reset HEAD~1
moves a branch reference backwards; it “rewrites history”.- This leaves your working files at the state of the latest commit (they are now modified), but resets the source tree to the specified commit
- The argument
--hard
resets your local files to the specified commit - The argument
--soft
keeps the modified files in the staging area
git revert HEAD
adds a new “automatic” commit that reverts the changes of the specified commit. It’s a reversecherry-pick
, kind of. Note that you specify the actual commit, not the state before the desired commit. Something likegit revert HEAD~3
reverts only that one commit, and not everything that happened after it!- You can also
git rebase -i HEAD~4
and interactively delete the commits you don’t want anymore
Moving work around: cherry-picking
If you have three commits across, say, three different branches, and want to copy these changes into your main branch:
git cherry-pick 862ff59 02659a3 54e8e5d
This creates three new commits under master.
Understand that cherry-pick makes only sense if the picked commit is not a direct ancestor of HEAD.
Tags
Branches can be moved around easily, they should not be used to permanently mark specific points in history.
Use tags instead for releases and big merges:
Tags can be checked out, but not moved around. If you check out a tag and commit on it, you will go into detached head mode.
Remotes
On GitHub, create a repository called sandbox
that is empty but contains an automatic README file. Then, get it on your local machine:
Remote branches
It’s crucial to understand the difference between local work and public work.
Remote branches have names such as origin/issue143
or upstream/master
. They reflect the state of remote repositories since you last talked to them (e.g. via git fetch
).
When you check them out, you are automatically in detached HEAD mode, because you can’t work on these branches directly.
Fetching
git fetch
synchronizes your local representation of the remote repository with the current state of the remote repository. It only updates the remote branches (e.g. origin/master
), not your local branches (e.g. master
).
Again: it does not change any local files! This allows you to inspect the changes and merge them later.
Without any arguments, git fetch
just gets all commits from the remote onto all the remote branches.
This command updates your local state of the remote branch, i.e. origin/doot
is now up to date.
In order to pull the remote branch theirBranch
, to your local branch myBranch
, use a colon refspec:
This behavior, although possible, is not recommended!
Pulling (fetching & merging)
To update your local state with new information from the remote, you could:
- cherry-pick from origin/master
- rebase from origin/master
- merge origin/master
Merging is the most common choice, and the command git pull
is (almost) just a shorthand for fetching and subsequently merging. You can also use git pull --rebase
to do a rebase instead of a merge. Note: A git pull origin myBranch
merges with your currently checked out branch, not necessarily with your myBranch
!
git pull
is only almost equivalent to git fetch; git merge
, because pull
is merging from remote only and ignores your local commits in your local branch which is tracking the remote branch being pulled from (Source).
Fancy pulling commands are very similar to the respective fetch & merge commands. A few examples of equivalent commands:
Note: The above pull
command means that if you are currently not on your local foo
branch but instead on someFeature
, you will merge the remote foo
branch into your someFeature
branch instead!
Pushing
- Note: Only push to bare repositories, i.e. repos that have no working directory. This ensures you don’t mess up another developer’s workdir.
To push the branch bugFix
to your remote origin
, you need to have write access, and nobody else should have pushed in the meantime (otherwise, pull
first):
This says: Go to the branch named “bugFix” in my repository, grab all the commits, and then go to the branch “bugFix” on the remote named “origin.” Place whatever commits are missing on that branch and then tell me when you’re done.
Without any arguments, git push
just pushes the currently checked out branch to the remote that it’s set to track:
If you’re not on a branch (but instead, e.g., in detached HEAD mode), this command will fail.
In order to push your local branch myBranch
to the remote branch theirBranch
, use a colon refspec:
Diverged history
When your local representation of the remote is out-of-date, your git push
might fail because it is now a very ambiguous situation. You first have to update your local repository.
The easiest fix is to rebase your work:
Alternatively, you can merge, which doesn’t move your work, but creates a merge commit instead:
Now, both your local and the remote repo have a merge commit with two ancestors, i.e. the remote changes and your local changes.
The rebase vs. merge discussion is a hot topic among developers. It boils down to “not rewriting history” (merging) vs. “having a clean commit tree” (rebasing).
Remote-tracking branches
The command git clone
usually does the following things:
- Download all remote branches (called
origin/*
) - Create only one local branch called
master
- Set
master
to track theorigin/master
branch
You can edit this default behavior. If you want a local branch called doot
instead of master
, but doot
should track master
, issue
The git pull
now updates your local branch doot
instead of master
!
Another way to set the tracking, if your branch doot
already exists, and you want doot
to track origin/master
, is
Stashing
git stash
goes back to the HEAD commit and stores all other (staged or unstaged) changes in a temporary stash to be reapplied later
When things go wrong: Merge conflicts
see here for a deeper introduction and here for a short summary.
Your options are basically:
- Resolve manually
- Cancel merge
- “omg just accept their stuff”
Misc lessons learned
git reset --hard HEAD
does not remove untracked files. If yougit add
them and then reset, they will be lost.