Git stash, merge, rebase & co.

Table of Contents

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

  1. a non-conflicting change
    pwd
    sed -i -es/multicore/manymanycore/g inria/storm.scm
    git add inria/storm.scm
    git commit -m 'Exascale, yay!'
    
  2. and now a conflicting change
    sed -i -e's/1.2.4/42.3/g' inria/storm.scm
    git add inria/storm.scm
    git commit -m 'Update StarPU to 42.3, yay!'
    

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

Sorry, your browser does not support SVG.

4.1.2 show example of linear and non-linear history

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!

Sorry, your browser does not support SVG.

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

gitlab-merge-request-rebase.png

6 rebase, “history rewriting”

6.1 Caveat: don’t rebase a published branch!

6.2 tools

  1. Magit (Emacs)

    magit.png

  2. Fugitive (Vim)
  3. command-line: ‘git rebase -i’ etc.

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!

Created: 2019-11-15 or. 18:46

Validate