Git Commands I Use
Git’s data model is a bunch of trees.
There’s the working tree which is the directory that you edit on-disk, the index (which I like to call the staging tree) which is a directory you can’t look at, and finally each commit is associated with its own tree. Each commit also points at its parent commit (or both, if it’s a merge commit).
When a commit is created, HEAD is updated:
- When HEAD is pointing at a branch, that branch is updated to point at the newly created commit;
- otherwise, HEAD was pointing at a commit (this is called “detached head”) and HEAD is changed to point at the newly created commit.
A <ref> is a branch, which points at a commit.
Every <ref> is also a <commit>, which is understood as the commit that the ref is currently pointing at; and every <commit> is also a <ref>, which is understood as a reference that points at <commit> and can never change.
Here are the commands I use (for the source material, ahem more detailed documentation, Git’s man pages are great: man git-<command>):
-
git statusto see an overview of which files have changed between HEAD and the index (“Changes to be committed”), files that have changed from the index to the working tree (“Changes not staged for commit”), and files from the working tree that don’t exist in the index (“Untracked files”). -
git diff --stagedto review changes between HEAD and the index, -
git diffto review changes between the index and the working tree (ignoring files that are in the working tree but not in index), and -
git diff <commit>to review changes between<ref>and the working tree. I commonly usegit diff HEAD~2to see what I’ve changed since two commits ago. -
git addto copy files from the working tree to the index, -
git add -pto interactively review changes in the working tree relative to the index, and for each hunk (small portion of the diff): (y) to apply the hunk to the index, (n) to skip this particular hunk, (s) to attempt to split this hunk into smaller portions, or (e) open your editor to manually change the hunk. -
git rm --cachedto remove a file (or directory with-r) from the index and leave the working tree unchanged. (note: without--cached,git rmwill also remove files and/or directories from the working tree, which I have never wanted to do in the history of Git) -
git committo copy the index tree into a new commit; -
git commit --amendcopies the index tree into the previous commit instead. -
git show <commit>to see<commit>’s metadata, and review the difference between that commit and its parent. -
git blameto see the commit that last touched each line of a file (some commits may be ignored bygit blame; see configuration variableblame.ignoreRevsFile). -
git reflogto see what you’ve done recently, separate from the main commit history. -
git checkout <ref>to set HEAD to<ref>. If<ref>is a commit, this will result in a detached head. (You probably want to usegit resetinstead.) -
git checkout <commit> .doesn’t update HEAD, and instead copies files from<commit>’s tree into the working tree. -
git cherry-pick <commit>to take the single commit<commit>, and create a new commit after applying<commit>’s diff from its parent. -
git rebase <ref>to:- Find the common ancestor between
<ref>and HEAD, - Update HEAD to the commit specified by
<ref>, - Cherry-pick each commit, in order, between the common ancestor and the initial HEAD.
This rewrites the commit graph into a linear sequence of commits with all changes on the current branch on top of any new commits in
<ref>, letting everyone else trivially fast-forward over changes from the current branch. - Find the common ancestor between
-
git rebase -i <ref>to interactively edit history between<ref>and now, or -
git rebase -i --rootto edit all history. -
git revert <commit>to take the single commit<commit>, and create a new commit after applying the reverse of<commit>’s diff from its parent. -
git reset --hard <commit>to update the current branch to point at the commit specified by<ref>, and copy that commit’s tree to overwrite the index and working tree.