How Do I __________ in Git
This is a compilation of common questions about git that I’ve seen online or have encountered myself. This is a work in progress, so organization isn’t that great.
For all of these, it’s a very good idea to read the man pages before running them to ensure it will do _exactly_ what you need done.
Undo a merge
git reset --hard ORIG_HEAD
Explanation: git reset
will reset the HEAD
to the specified commit, which
in this case in ORIG_HEAD
. This will be a reference to the commit right
before the merge since git merge
saves the old HEAD
into ORIG_HEAD
before
performing the merge. Most importantly here is --hard
which will reset the
index and working tree so it’s as if the merge never happened; if you use
—soft it’ll just change the HEAD
reference.
Discard local uncommitted changes
git checkout -- FILENAME
Explanation: git checkout
will change the working tree to match the index
or whichever branch/commit you’ve specified. In this case, you haven’t
specified anything so it’ll update FILENAME
to match what’s in the index for
the current branch.
Modify the last commit
git commit --amend
Explanation: This will open up $EDITOR
to let you edit your last commit
message. As with regulare git commit
it’ll take the -m
flag. Most
importantly, if you have use git add
right before the amend, it’ll add those
changes into the commit.
See the original version during a merge conflict
git config merge.conflictstyle diff3
Explanation: This will show changes in the current branch, then changes
from the common ancestor, and then the branch you’re merging in. You’ll need to
have this in your config before you try to merge, but I can’t think of a time
when you wouldn’t want this, so I keep it in my global ~/.gitconfig
.
Avoid ‘merge origin/master into master’ commits
git pull --rebase
Explanation: When your master branch and the remote’s master branch have
diverted git pull
will try to merge the remote one into your local one.
Unfortunately, this creates an unnecessary merge commit which can be avoided by
simply replaying your commits on top of the remote’s master branch (which is
what --rebase
does).
Note that this is dependent on your workflow, and you probably shouldn’t use it for every pull. If you’re finding your changes often conflict with other people’s, it’s a good idea to find a workflow that keeps people from stepping on each other’s toes. See Atlassian’s [Comparing Workflows](https://www.atlassian.com/git/tutorials/comparing-workflows/) tutorial for ideas.
Undo the last commit
git reset --soft HEAD~
Explanation: This will reset the HEAD
to point to HEAD~
which is its
first ancestor (i.e. parent), while leaving your working tree unchanged. Since
reset saves the old HEAD
to ORIG_HEAD
, you can then use git commit -c
ORIG_HEAD
to reuse the old commit message along with the authorship information.
Discard local commits when pulling
git fetch --all
git reset --hard origin/branchname
Explanation: git fetch
will download all the commits from the remote
without trying to merge them into your local branch. Then the git reset
will
reset your current branch head to origin/branchname
. Remember, branches and
heads are really only references to specific commit objects.
Add only part of a file
git add -p FILENAME
Explanation: This will present the diff between the index and the working
tree version of the file, and will ask you which sections of the diff you want
to stage. You can use y
to stage n
to skip it s
to split the given
section q
to skip the rest of the diff, and ?
to print the help. Read
about the patch subcommand in the “Interactive mode” section of the man page
for git-add
for more details.
Delete a remote branch
git push origin --delete BRANCH # >=1.7.0
git push origin :BRANCH # <1.7.0
Explanation: The first version is fairly self-explanatory. The older
version makes sense when you think that you can push using git push
origin LOCAL:REMOTE
where LOCAL
is the local branch name and
REMOTE
is the remote branch name; then omitting LOCAL
is like
pushing _nothing_ to the remote branch.
Remove untracked files from the working tree
git clean -- . # OR
git clean -d -- . # include directories
Clean up the commits in the current branch
git rebase -i
Explanation: git rebase
reapplies commits to a different base. For
example, you can use it to change the base of the current branch to be the
current master
instead of merging master
into the current branch (thus
keeping your history a bit cleaner). When passing -i
of --interactive
, git
gives you a list of commits in the current branch (from when it diverged) which
you can reorder, squash, or delete by modifying the lines in the opened file. A
comment at the bottom explains which actions are available.
Apply chain of commits from a different branch
git cherry-pick <commit1>^1..<commit2>
Explanation: This will cherry-pick all the commits in the range and apply
them on top of the current HEAD
. Note that ..
notation will not include the
first commit, so we use ^1
to get the first parent of commit1
.