Table of Contents
Table of Contents

How do I add only a portion of a file?

git add --patch <file>

This brings up an interactive interface that moves through each individual change to a file, allowing you to only stage the changes that you want.

$ git add --patch package.json
diff --git a/package.json b/package.json
index 7a558a3..e03ce3f 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,6 @@
   "name": "package",
   "version": "0.4.3",
   "description": "this is an example package",
-  "keywords": ["key", "middleware", "connect"],
   "repository": "git://",
   "author": "Joe Smith <> (",
   "repository": "git://",
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y

Table of Contents

How do I squash commits?

There are multiple ways of squashing commits but the most recommended and straight forward is to use an interactive rebase, eg

git rebase -i HEAD~4 # interactively rebase from 3 commits ago

This command will bring up your editor with some helpful documentation and list of those commits and messages. The commits are listed in order with the oldest commit at the top and the latest commit at the bottom.

pick f53d15b fixed edge case with IE5
pick 930c0e5 added code coverage
pick fa7c471 fixed lint errors
pick fb57c85 added feature Foo

# Rebase 0a4b808..db5d725 onto 0a4b808
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
# These lines can be re-ordered; they are executed from top to bottom.
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
# Note that empty commits are commented out

To squash the last 4 commits into the most recent, you would change pick to squash for commits 2, 3, and 4.

pick f53d15b fixed edge case with IE5
squash 930c0e5 added code coverage
squash fa7c471 fixed lint errors
squash fb57c85 added feature Foo

When the file is saved and the editor is quit, git will automatically squash those 4 commits into one. Your editor will then pop up again allowing you to change the commit message for the resulting commit(s).

Table of Contents

How do I change my last commit message?

git commit --amend --only

Or, without staged changes:

git commit --amend

--amend without other options combines the currently staged changes with the last commit and then opens an editor to update the commit message. If you have staged changes, they will be added.

To update the last message even if there are staged changes (git status reports files under Changes to be committed) then you can use the -o (or --only) option to indicate you want to amend the last commit but only use the files that were previously committed.

Table of Contents
Table of Contents
Table of Contents

How do I compare branches?

Find commits on remote master branch which are not on our local master branch:

git cherry -v origin/master master

Find commits on local master branch which are not on our local feature branch:

git cherry -v master feature

Find commits added since the 1.0.0 tag:

git cherry -v v1.0.0 master

Table of Contents

How do I create a branch?

git branch <branch>      # just creates a branch off the current sha
git checkout <branch>    # actually moves to the branch

This can be simplified to:

git checkout -b <branch> # branches and moves to the branch in one command

Table of Contents
Table of Contents

How do I delete a branch?

Delete a local branch feature:

git branch -d feature

This will fail if the branch is not merged. To delete the branch regardless:

git branch -D feature

To delete a remote branch feature on remote origin (warning: There is no confirmation!):

git push origin :feature

Note: git-branch documentation lists documentation for the option -r which works on remote tracking branches, not branches on the remote; git branch -D -r origin/feature will delete the remote tracking branch origin/feature, not the branch feature on remote origin. Pulling/fetching from the remote again will recreate that tracking branch.

To delete remote tracking branches that no longer exist on the remote:

git fetch --prune

Table of Contents
Table of Contents

How do I ignore a file pattern?

git ignore '*.swp'

If you haven’t ignored anything yet, this creates a .gitignore file which you probably want to add and track.

git add .gitignore
git commit -m 'added .gitignore'

Table of Contents
Table of Contents

How do I undo a commit?

Do you want to undo the commit and never see the changes ever again?

git reset --hard HEAD~1

Do you want to keep your changes and just undo the actual act of committing?

git reset HEAD~1

Table of Contents
Table of Contents
Table of Contents
Table of Contents

How do I undo git add?

git reset


git reset file.txt

git add simply stages changes to be committed. To undo that action, all that’s needed is to git reset the file or list of files.

To undo a commit, see How do I undo a commit?

Table of Contents

What if I forgot to add a file in my last commit?

git add file.js     # the file that needed to be included
git commit --amend  # amend the commit done before step 1 with the added file

This will add the file to the previous commit and replace it with a new commit.

This can be simplified into one command:

git commit --amend file.js

If the commit message doesn’t need to be updated:

git commit --amend --no-edit file.js

If all the edited files need to be added to the last commit:

git commit --amend --no-edit --all

Table of Contents

What does "Changing History" mean?

In git, each commit is tagged with a unique SHA-1 hash. These are critical when resolving differences between sources that have diverged. This sequence of SHAs is referred to as the “history” and “changing history” is regenerating those hashes via any number of legitimate means.

A modified history makes it very difficult to resolve differences between two repositories because, from git’s perspective, the SHAs have changed and commits that should refer to the same changes now look to be two different changes at different times.

Rewriting history has a number of legitimate uses but requires communication proportional to the number of people who have already based development off the history that is to be changed. It is important that changes are resolved before history is rewritten and that usually means waiting for all important work to be pushed.

Rewriting local history up to the point of shared changes is rarely a problem. The number of people you need to communicate with is usually limited to just you.

On shared feature branches, the burden of communication increases to the people who are developing with you on that branch. This is also usually not a problem if you expect branches to be short lived and highly collaborative (assuming high communication).

On mainline branches that anyone could base off of for any arbitrary work (eg “master” or “develop”), changing history is very problematic and should only be done in extreme cases where the cost is understood. Problems occur because you can rarely be sure you’ve communicated with everybody you need to in order to make sure important changes are pushed before a history modification.

See also What is local history/shared history?

Table of Contents

What is a "detached head"?

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

This is not an error message and is nothing to be worried about. This is simply a notice that you are not attached to an actual branch. For example, take the following commits on master:

master    A-B-C-D-E-F-G

Using the example above where the master branch has commits A-G, if you check out master you will be placed at the ‘tip’ of master, commit G. If you remain at the tip of a branch, you are considered “attached.”

If you check out an arbitrary commit, you are no longer necessarily associated with a branch and are considered “detached.”

This is useful to explore the state of code at a commit, and you can also create and move to a branch from a “detached head” state.

If this state was unintentional, you can get back to where you likely want to be by checking out the branch you expected to be on, eg

$ git checkout master
Previous HEAD position was 183409d... added file.txt
Switched to branch 'master'

Try navigating through detached head by yourself. The following block sets up a fresh git repository with two commits.

git init
touch file.txt
git add file.txt
git commit -m 'added file.txt'
touch file2.txt
git add file2.txt
git commit -m 'added file2.txt'

HEAD is now at the tip of master. Check out the previous commit by issuing the command git checkout HEAD~1 which references the commit 1 before HEAD.

$ git checkout HEAD~1
git co HEAD~1
Note: checking out 'HEAD~1'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 183409d... added file.txt

To get back to the tip of master, checkout master.

$ git checkout master
Previous HEAD position was 183409d... added file.txt
Switched to branch 'master'

Notice, though, if you try to check out what commit the tip of master was initially pointing to you still will be detached!

$ git co ec3...7da
Previous HEAD position was 183409d... added file.txt
HEAD is now at ec36c1b... added file2.txt
$ git status
HEAD detached at ec36c1b
nothing to commit, working directory clean

Table of Contents

What is a "remote"?

The term “remote” is any remote destination that you may want to push or pull from. This is often a git repository hosted on a git server like those run by Github.

You can have multiple remotes.

You can view the remotes you have set with git remote and git remote -v gives you more important information.

$ git remote -v
origin (fetch)
origin (push)

You can add new remotes via git remote add <destination> eg

$ git remote add michaelficarra

You can change the destination via git remote set-url <remote> <destination>

$ git remote set-url origin

Table of Contents

What is local history/shared history?

“Remote history” or “Shared History” is used to refer to history that is shared with others. “Local history” is used to refer to changes that have never been shared.

For the following commit history, “Shared History”and “Local History” boundaries are shown,

A-B-C-D-E                origin/master

A-B-C-D-E-F-G-H-I        origin/feature1

A-B-C-D-E-F-G-H-I-J-K-J  feature1 (local)
|       | |     | |   |
|       | |     | +-+-+
|       | |     |   |
|       | +--+--+   Local History
|       |    |
+---+---+  Shared History (branch)
Shared History (master)

Table of Contents

What is "origin"?

Origin is the default name for the remote server. “Remotes” can be named anything, you can see the names of all your remotes with the command remote

$ git remote -v
origin (fetch)
origin (push)

Table of Contents

What is rebasing?

Rebasing is establishing a new base for a series of commits.

In the example below, the branch feature deviated at commit B, while the master branch moved along in parallel.

A-B-C-D-E    master
    X-Y-Z    feature

You can rebase with the rebase command. For example, to rebase the feature branch on master:

$ git checkout feature
$ git rebase master

Rebasing essentially rewinds the commits on a branch, brings the branch up to date with the rebase target, and then replays the rewound commits over it, leaving the timeline looking like this.

A-B-C-D-E        master
          X'-Y'-Z'  feature

Warning this changes history, see also What does changing history mean?

Table of Contents

What is squashing?

Squashing is the act of turning multiple git commits into fewer. There are many reasons you might want to do this but the most straightforward is to simply keep the commit history cleaner and filled with high value changes.

Consider the following set of commits

f53d15b fixed edge case with IE5
930c0e5 increased code coverage
fa7c471 fixed lint errors
fb57c85 added feature Foo

In a local repository that level of detail may be useful; at some point a regression may have been introduced while fixing lint errors and you would be able to revert to a previous commit to do some testing.

In the grand scheme of living software, this level of granularity becomes noisier than it is worth. When preparing code to enter a main line branch it can become more valuable to squash commits into logical chunks so that the history becomes more valuable as a record of important changes. The following commits could then be squashed into a single commit, eg

a3545a5 added feature Foo

See also how do I squash commits?

Table of Contents

What is difference between master & HEAD?

master is the common name for the default branch. It doesn’t need to exist, but it often does.

HEAD can be thought of as a variable pointing to a specific commit. It can change and isn’t related to a branch.

Issuing new commits changes HEAD, checking anything out changes HEAD.

Table of Contents

What is the difference between fetch and pull?

git pull [remote] [branch] is the same as

git fetch [remote] [branch]
git merge [remote][/branch]

git pull --rebase [remote] [branch] is the same as

git fetch [remote] [branch]
git rebase [remote][/branch]

Fork me on GitHub