Git Flightrules
Git Flightrules
1
– I pulled from/into the wrong branch
– I want to discard local commits so my branch is the same as one on
the server
– I committed to master instead of a new branch
– I made several commits on a single branch that should be on different
branches
– I want to delete local branches that were deleted upstream
– I accidentally deleted my branch
– I want to delete a branch
• Rebasing and Merging
– I rebased, but I don’t want to force push.
– I need to combine commits
– Safe merging strategy
– I need to merge a branch into a single commit
– I want to combine only unpushed commits
– Check if all commits on a branch are merged
– Possible issues with interactive rebases
– The rebase editing screen says ‘noop’
– There were conflicts
• Miscellaneous Objects
– Clone all submodules
– Delete tag
– Recover a deleted tag
– Deleted Patch
• Tracking Files
– I want to change a file name’s capitalization, without changing the
contents of the file.
– I want to remove a file from git but keep the file
• Configuration
– I want to add aliases for some git commands
– I want to cache a username and password for a repository
• I’ve no idea what I did wrong
• Other Resources
• Books
• Tutorials
• Scripts and Tools
• GUI Clients
Editing Commits
2
(master)$ git show
or
$ git log -n1 -p
### I wrote the wrong thing in a commit message
If you wrote the wrong thing and the commit has not yet been pushed, you can
do the following to change the commit message:
$ git commit --amend
You can specify the commit message inline if you want:
$ git commit --amend -m 'xxxxxxx'
If you have already pushed the message, you can amend the commit and force
push, but this is not recommended.
### I committed with the wrong name and email configured
If it’s a single commit, amend it
$ git commit --amend --author "New Authorname <[email protected]>"
If you need to change all of history, see the man page for ‘git filter-branch’.
### I want to remove a file from a commit
In order to remove a file from a commit, do the following:
$ git checkout HEAD^ myfile
$ git add -A
$ git commit --amend
This is particularly useful when you have an open patch and you have commited
an unnecessary file, and need to force push to update the patch on a remote.
### I want to delete or remove my last commit
If you need to delete pushed commits, you can use the following. However, it
will irreversabily change your history, and mess up the history of anyone else
who had already pulled from the repository. In short, if you’re not sure, you
should never do this, ever.
$ git reset HEAD^ --hard
$ git push -f [remote] [branch]
If you haven’t pushed, to reset Git to the state it was in before you made your
last commit (while keeping your staged changes):
(my-branch*)$ git reset --soft HEAD@{1}
This only works if you haven’t pushed. If you have pushed, the only truly safe
thing to do is git revert SHAofBadCommit. That will create a new commit
that undoes all the previous commit’s changes. Or, if the branched you pushed
3
to is rebase-safe (ie. other devs aren’t expected to pull from it), you can just
use git push -f. For more, see the above section.
### Delete/remove arbitrary commit
The same warning applies as above. Never do this if possible.
$ git rebase --onto SHA1_OF_BAD_COMMIT^ SHA1_OF_BAD_COMMIT
$ git push -f [remote] [branch]
Or do an interactive rebase and remove the line(s) correspoding to commit(s)
you want to see removed.
### I tried to push my amended commit to a remote, but I got an error
message
To https://github.com/yourusername/repo.git
! [rejected] mybranch -> mybranch (non-fast-forward)
error: failed to push some refs to 'https://github.com/tanay1337/webmaker.org.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Note that, as with rebasing (see below), amending replaces the old commit
with a new one, so you must force push (-f) your changes if you have already
pushed the pre-amended commit to your remote. Be careful when you do this
– always make sure you specify a branch!
(my-branch)$ git push origin mybranch -f
In general, avoid force pushing. It is best to create and push a new commit
rather than force-pushing the amended commit as it has will cause conflicts in
the source history for any other developer who has interacted with the branch
in question or any child branches.
### I accidentally did a hard reset, and I want my changes back
If you accidentally do git reset --hard, you can normally still get your commit
back, as git keeps a log of everything for a few days.
(master)$ git reflog
You’ll see a list of your past commits, and a commit for the reset. Choose the
SHA of the commit you want to return to, and reset again:
(master)$ git reset --hard SHA1234
And you should be good to go.
4
Staging
Unstaged Edits
5
To reset only a specific file, you can use that the filename as the argument:
$ git reset filename
Branches
6
Alternatively, if you don’t want to use HEADˆ, find out what the commit hash
you want to set your master branch to (git log should do the trick). Then
reset to that hash. git push will make sure that this change is reflected on
your remote.
For example, if the hash of the commit that your master branch is supposed to
be at is a13b85e:
(master)$ git reset --hard a13b85e
HEAD is now at a13b85e
Checkout the new branch to continue working:
(master)$ git checkout my-branch
### I made several commits on a single branch that should be on different
branches
Say you are on your master branch. Running git log, you see you have made
two commits:
(master)$ git log
commit e3851e817c451cc36f2e6f3049db528415e3c114
Author: Alex Lee <[email protected]>
Date: Tue Jul 22 15:39:27 2014 -0400
commit 5ea51731d150f7ddc4a365437931cd8be3bf3131
Author: Alex Lee <[email protected]>
Date: Tue Jul 22 15:39:12 2014 -0400
commit a13b85e984171c6e2a1729bb061994525f626d14
Author: Aki Rose <[email protected]>
Date: Tue Jul 21 01:12:48 2014 -0400
First commit
Let’s take note of our commit hashes for each bug (e3851e8 for #21, 5ea5173
for #14).
First, let’s reset our master branch to the correct commit (a13b85e):
(master)$ git reset --hard a13b85e
HEAD is now at a13b85e
Now, we can create a fresh branch for our bug #21 branch:
7
(master)$ git checkout -b 21
(21)$
Now, let’s cherry-pick the commit for bug #21 on top of our branch. That
means we will be applying that commit, and only that commit, directly on top
of whatever our head is at.
(21)$ git cherry-pick e3851e8
At this point, there is a possibility there might be conflicts. See the There
were conflicts section in the interactive rebasing section above for how to
resolve conflicts.
Now let’s create a new branch for bug #14, also based on master
(21)$ git checkout master
(master)$ git checkout -b 14
(14)$
And finally, let’s cherry-pick the commit for bug #14:
(14)$ git cherry-pick 5ea5173
### I want to delete local branches that were deleted upstream Once you
merge a pull request on github, it gives you the option to delete the merged
branch in your fork. If you aren’t planning to keep working on the branch, it’s
cleaner to delete the local copies of the branch so you don’t end up cluttering
up your working checkout with a lot of stale branches.
$ git fetch -p
### I accidentally deleted my branch
If you’re regularly pushing to remote, you should be safe most of the time. But
still sometimes you may end up deleting your branches. Let’s say we create a
branch and create a new file:
(master)$ git checkout -b my-branch
(my-branch)$ git branch
(my-branch)$ touch foo.txt
(my-branch)$ ls
README.md foo.txt
Let’s add it and commit.
(my-branch)$ git add .
(my-branch)$ git commit -m 'foo.txt added'
(my-branch)$ foo.txt added
1 files changed, 1 insertions(+)
create mode 100644 foo.txt
(my-branch)$ git log
commit 4e3cd85a670ced7cc17a2b5d8d3d809ac88d5012
8
Author: siemiatj <[email protected]>
Date: Wed Jul 30 00:34:10 2014 +0200
foo.txt added
commit 69204cdf0acbab201619d95ad8295928e7f411d5
Author: Kate Hudson <[email protected]>
Date: Tue Jul 29 13:14:46 2014 -0400
9
To delete a local branch:
(master)$ git branch -D my-branch
10
pick e3851e8 another fix
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# rebase in progress; onto 8074d12
# You are currently editing a commit while rebasing branch 'master' on '8074d12'.
11
#
# Changes to be committed:
# modified: README.md
#
If everything is successful, you should see something like this:
(master)$ Successfully rebased and updated refs/heads/master.
12
noop
That means you are trying to rebase against a branch that is at an identical
commit, or is ahead of your current branch. You can try:
• making sure your master branch is where it should be
• rebase against HEAD~2 or earlier instead
#### There were conflicts
If you are unable to successfully complete the rebase, you may have to resolve
conflicts.
First run git status to see which files have conflicts in them:
(my-branch)$ git status
On branch my-branch
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
In this example, README.md has conflicts. Open that file and look for the fol-
lowing:
<<<<<<< HEAD
some code
=========
some code
>>>>>>> new-commit
You will need to resolve the differences between the code that was added in your
new commit (in the example, everything from the middle line to new-commit)
and your HEAD.
Sometimes these merges are complicated and you should use a visual diff editor:
(master*)$ git mergetool -t opendiff
After you have resolved all conflicts and tested your code, git add the files you
have changed, and then continue the rebase with git rebase --continue
(my-branch)$ git add README.md
(my-branch)$ git rebase --continue
If after resolving all the conflicts you end up with an identical tree to what it
was before the commit, you need to git rebase --skip instead.
If at any time you want to stop the entire rebase and go back to the original
state of your branch, you can do so:
(my-branch)$ git rebase --abort
13
## Miscellaneous Objects
### Clone all submodules
$ git clone --recursive git://github.com/foo/bar.git
If already cloned:
$ git submodule update --init --recursive
### Delete tag
$ git tag -d <tag_name>
$ git push <remote> :refs/tags/<tag_name>
### Recover a deleted tag
If you want to recover a tag that was already deleted, you can do so by following
these steps: First, you need to find the unreachable tag:
$ git fsck --unreachable | grep tag
Make a note of the tag’s hash. Then, restore the deleted tag with following,
making use of git’s update-ref:
$ git update-ref refs/tags/<tag_name> <hash>
Your tag should now have been restored.
### Deleted Patch
If someone has sent you a pull request on GitHub, but then deleted their original
fork, you will be unable to clone their commits or to use git am. In such cases,
it is best to manually look at their commits and copy them into a new branch
on your local. Then, commit.
After commiting, change the author of the previous commit. To do this, see
how to change author. Then, apply whatever changes needed on to, and make
a new pull request.
Tracking Files
### I want to change a file name’s capitalization, without changing the con-
tents of the file.
(master)$ git mv --force myfile MyFile
### I want to remove a file from git but keep the file
(master)$ git rm --cached log.txt
14
Configuration
15
every time HEAD changes, a new entry is added to the reflog. This only works
for local repositories, sadly, and it only tracks movements (not changes to a file
that weren’t recorded anywhere, for instance).
(master)$ git reflog
0a2e358 HEAD@{0}: reset: moving to HEAD~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to master
c10f740 HEAD@{2}: checkout: moving from master to 2.2
The reflog above shows a checkout from master to the 2.2 branch and back.
From there, there’s a hard reset to an older commit. The latest activity is
represented at the top labeled HEAD@{0}.
If it turns out that you accidentially moved back, the reflog will contain the
commit master pointed to (0254ea7) before you accidentially dropped 2 com-
mits.
$ git reset --hard 0254ea7
Using git reset it is then possible to change master back to the commit it was
before. This provides a safety net in case history was accidentially changed.
(copied and edited from Source).
Other Resources
Books
Tutorials
16
• git-tips - Small git tips
• git-fire - git-fire is a Git plugin that helps in the event of an emergency
by adding all current files, committing, and pushing to a new branch (to
prevent merge conflicts).
GUI Clients
17