Git stash, merge, rebase & co.
Table of Contents
- 1. discarding or stashing away local changes
- 2. dealing with merge conflicts
- 3. context: code review/development iteration
- 4. keeping the history linear
- 5. rebasing
- 6. rebase, “history rewriting”
1 discarding or stashing away local changes
1.1 git reset --hard
to discard uncommitted changes
1.2 git stash
to stash away uncommitted changes
Run git stash pop
to reinstate those changes in the working tree,
uncommitted.
2 dealing with merge conflicts
2.1 let’s create a conflict!
2.1.1 first, create our branch and commit something
cd /tmp
git clone https://gitlab.inria.fr/guix-hpc/guix-hpc
cd guix-hpc
git checkout -b mes-trucs 16bf282dd3e53ca965921381a8a55f18f78970fb
2.1.2 second, commit something
2.1.3 second, try to merge master
, fasten your seat belts!
git branch
git merge master
Oh la la!
2.1.4 what’s the status?
git status
(magit-status "/tmp/guix-hpc")
2.1.5 let’s edit the conflict
2.1.6 once you’re done
git add inria/storm.scm # add change to the index
git merge --continue # resume merge operation
2.1.7 view the result
3 context: code review/development iteration
3.1 the process: (1) submit, (2) review, (3) goto 1
3.2 iteration history
3.2.1 squash intermediate commits because they don’t matter
3.2.2 adjust commits and commit logs according to review
4 keeping the history linear
4.1 what ‘git merge’ and ‘git pull’ (and ‘git push’ sometimes) do
4.1.1 creates a “merge commit”
see the awesome Git for Computer Scientists
4.2 why should i care?
4.2.1 helps understand code evolution
4.2.2 helps bisection (‘git bisect’)
4.2.3 possibly helps continuous integration
4.3 visualizing the history
- using
gitk
(which is part of Git) - using Magit (in Emacs)
- using a Web interface (GitLab, cgit, etc.)
4.4 pull/merge requests
4.4.1 by default, they introduce merge commits!
4.5 note: sometimes you do need parallel dev branches, that’s fine!
5 rebasing
5.1 the Git commit graph
Do not miss Git for Computer Scientists!
5.2 rebasing your changes before pushing
For example, assuming you are working on the ‘master’ branch and have a bunch of local commits ready to be pushed, you would run these commands:
$ git pull --rebase # fetch remote changes, and rebase on top of them
$ git push
Sometimes ‘git pull –rebase’ will result in conflicts that need to be resolved. Assuming ‘foo.cpp’ has a conflict, you would edit it to fix those conflicts (look for “>>>”), and then:
$ git add foo.cpp
$ git rebase --continue
5.3 make ‘git pull’ rebase by default
git config branch.master.rebase true
From now on ‘git pull’ will always rebase. \o/
5.4 tell GitLab to rebase when you accept merge requests
6 rebase, “history rewriting”
6.1 Caveat: don’t rebase a published branch!
6.3 amending the last commit of a branch
git add foo # stage changes
git commit --amend # amend the last commit on the branch
6.4 rebasing a branch on top of another one
This will simplify the reviewers life by make sure the changes apply on the latest ‘master’, for example.
git checkout master
git pull # update my copy of 'master'
git checkout my-feature-branch
git rebase master # rebase 'my-feature-branch' on 'master'
6.5 squashing, dropping, reordering, rewriting commits
All with ‘git rebase -i’ (or similar in your favorite UI). Glossary:
- squashing two or more commits: turning them into a single commit
- dropping: get rid of commits you don’t like, after all
- reodering: you can change the order of commits in the history
- rewriting: change the commit log and/or what the commit does
6.6 pro tip: autosquash (thanks bgoglin!)
- Write “squash! the summary line” in your commit log and then ‘git rebase n–autosquash’ will automatically flag it as candidate for squashing with the commit that has “the summary line”. See git-rebase(1). Also works with “fixup!” (difference is that the fixup commit log is discarded.)
git config branch.THE-BRANCH.autoSquash true
- Actually, ‘git commit –fixup ID’ creates the right summary line!