#+TITLE: Git stash, merge, rebase & co.
#+STARTUP: overview hidestars inlineimages

* discarding or stashing away local changes

** =git reset --hard= to discard uncommitted changes

** =git stash= to stash away uncommitted changes

Run =git stash pop= to reinstate those changes in the working tree,
uncommitted.


* dealing with merge conflicts
  :PROPERTIES:
  :header-args:sh: :session *sh-for-merge-conflicts* :results output
  :END:

** let’s create a conflict!

*** first, create our branch and commit something

#+BEGIN_SRC sh
  cd /tmp
  git clone https://gitlab.inria.fr/guix-hpc/guix-hpc
  cd guix-hpc
  git checkout -b mes-trucs 16bf282dd3e53ca965921381a8a55f18f78970fb
#+END_SRC

#+RESULTS:
#+begin_example

Cloning into 'guix-hpc'...
warning: redirecting to https://gitlab.inria.fr/guix-hpc/guix-hpc.git/
remote: Enumerating objects: 172, done.
(1/172)           remote: Counting objects:   1% (2/172)           remote: Counting objects:   2% (4/172)           remote: Counting objects:   3% (6/172)           remote: Counting objects:   4% (7/172)           remote: Counting objects:   5% (9/172)           remote: Counting objects:   6% (11/172)           remote: Counting objects:   7% (13/172)           remote: Counting objects:   8% (14/172)           remote: Counting objects:   9% (16/172)           remote: Counting objects:  10% (18/172)           remote: Counting objects:  11% (19/172)           remote: Counting objects:  12% (21/172)           remote: Counting objects:  13% (23/172)           remote: Counting objects:  14% (25/172)           remote: Counting objects:  15% (26/172)           remote: Counting objects:  16% (28/172)           remote: Counting objects:  17% (30/172)           remote: Counting objects:  18% (31/172)           remote: Counting objects:  19% (33/172)           remote: Counting objects:  20% (35/172)           remote: Counting objects:  21% (37/172)           remote: Counting objects:  22% (38/172)           remote: Counting objects:  23% (40/172)           remote: Counting objects:  24% (42/172)           remote: Counting objects:  25% (43/172)           remote: Counting objects:  26% (45/172)           remote: Counting objects:  27% (47/172)           remote: Counting objects:  28% (49/172)           remote: Counting objects:  29% (50/172)           remote: Counting objects:  30% (52/172)           remote: Counting objects:  31% (54/172)           remote: Counting objects:  32% (56/172)           remote: Counting objects:  33% (57/172)           remote: Counting objects:  34% (59/172)           remote: Counting objects:  35% (61/172)           remote: Counting objects:  36% (62/172)           remote: Counting objects:  37% (64/172)           remote: Counting objects:  38% (66/172)           remote: Counting objects:  39% (68/172)           remote: Counting objects:  40% (69/172)           remote: Counting objects:  41% (71/172)           remote: Counting objects:  42% (73/172)           remote: Counting objects:  43% (74/172)           remote: Counting objects:  44% (76/172)           remote: Counting objects:  45% (78/172)           remote: Counting objects:  46% (80/172)           remote: Counting objects:  47% (81/172)           remote: Counting objects:  48% (83/172)           remote: Counting objects:  49% (85/172)           remote: Counting objects:  50% (86/172)           remote: Counting objects:  51% (88/172)           remote: Counting objects:  52% (90/172)           remote: Counting objects:  53% (92/172)           remote: Counting objects:  54% (93/172)           remote: Counting objects:  55% (95/172)           remote: Counting objects:  56% (97/172)           remote: Counting objects:  57% (99/172)           remote: Counting objects:  58% (100/172)           remote: Counting objects:  59% (102/172)           remote: Counting objects:  60% (104/172)           remote: Counting objects:  61% (105/172)           remote: Counting objects:  62% (107/172)           remote: Counting objects:  63% (109/172)           remote: Counting objects:  64% (111/172)           remote: Counting objects:  65% (112/172)           remote: Counting objects:  66% (114/172)           remote: Counting objects:  67% (116/172)           remote: Counting objects:  68% (117/172)           remote: Counting objects:  69% (119/172)           remote: Counting objects:  70% (121/172)           remote: Counting objects:  71% (123/172)           remote: Counting objects:  72% (124/172)           remote: Counting objects:  73% (126/172)           remote: Counting objects:  74% (128/172)           remote: Counting objects:  75% (129/172)           remote: Counting objects:  76% (131/172)           remote: Counting objects:  77% (133/172)           remote: Counting objects:  78% (135/172)           remote: Counting objects:  79% (136/172)           remote: Counting objects:  80% (138/172)           remote: Counting objects:  81% (140/172)           remote: Counting objects:  82% (142/172)           remote: Counting objects:  83% (143/172)           remote: Counting objects:  84% (145/172)           remote: Counting objects:  85% (147/172)           remote: Counting objects:  86% (148/172)           remote: Counting objects:  87% (150/172)           remote: Counting objects:  88% (152/172)           remote: Counting objects:  89% (154/172)           remote: Counting objects:  90% (155/172)           remote: Counting objects:  91% (157/172)           remote: Counting objects:  92% (159/172)           remote: Counting objects:  93% (160/172)           remote: Counting objects:  94% (162/172)           remote: Counting objects:  95% (164/172)           remote: Counting objects:  96% (166/172)           remote: Counting objects:  97% (167/172)           remote: Counting objects:  98% (169/172)           remote: Counting objects:  99% (171/172)           remote: Counting objects: 100% (172/172)           remote: Counting objects: 100% (172/172), done.
(1/72)           remote: Compressing objects:   2% (2/72)           remote: Compressing objects:   4% (3/72)           remote: Compressing objects:   5% (4/72)           remote: Compressing objects:   6% (5/72)           remote: Compressing objects:   8% (6/72)           remote: Compressing objects:   9% (7/72)           remote: Compressing objects:  11% (8/72)           remote: Compressing objects:  12% (9/72)           remote: Compressing objects:  13% (10/72)           remote: Compressing objects:  15% (11/72)           remote: Compressing objects:  16% (12/72)           remote: Compressing objects:  18% (13/72)           remote: Compressing objects:  19% (14/72)           remote: Compressing objects:  20% (15/72)           remote: Compressing objects:  22% (16/72)           remote: Compressing objects:  23% (17/72)           remote: Compressing objects:  25% (18/72)           remote: Compressing objects:  26% (19/72)           remote: Compressing objects:  27% (20/72)           remote: Compressing objects:  29% (21/72)           remote: Compressing objects:  30% (22/72)           remote: Compressing objects:  31% (23/72)           remote: Compressing objects:  33% (24/72)           remote: Compressing objects:  34% (25/72)           remote: Compressing objects:  36% (26/72)           remote: Compressing objects:  37% (27/72)           remote: Compressing objects:  38% (28/72)           remote: Compressing objects:  40% (29/72)           remote: Compressing objects:  41% (30/72)           remote: Compressing objects:  43% (31/72)           remote: Compressing objects:  44% (32/72)           remote: Compressing objects:  45% (33/72)           remote: Compressing objects:  47% (34/72)           remote: Compressing objects:  48% (35/72)           remote: Compressing objects:  50% (36/72)           remote: Compressing objects:  51% (37/72)           remote: Compressing objects:  52% (38/72)           remote: Compressing objects:  54% (39/72)           remote: Compressing objects:  55% (40/72)           remote: Compressing objects:  56% (41/72)           remote: Compressing objects:  58% (42/72)           remote: Compressing objects:  59% (43/72)           remote: Compressing objects:  61% (44/72)           remote: Compressing objects:  62% (45/72)           remote: Compressing objects:  63% (46/72)           remote: Compressing objects:  65% (47/72)           remote: Compressing objects:  66% (48/72)           remote: Compressing objects:  68% (49/72)           remote: Compressing objects:  69% (50/72)           remote: Compressing objects:  70% (51/72)           remote: Compressing objects:  72% (52/72)           remote: Compressing objects:  73% (53/72)           remote: Compressing objects:  75% (54/72)           remote: Compressing objects:  76% (55/72)           remote: Compressing objects:  77% (56/72)           remote: Compressing objects:  79% (57/72)           remote: Compressing objects:  80% (58/72)           remote: Compressing objects:  81% (59/72)           remote: Compressing objects:  83% (60/72)           remote: Compressing objects:  84% (61/72)           remote: Compressing objects:  86% (62/72)           remote: Compressing objects:  87% (63/72)           remote: Compressing objects:  88% (64/72)           remote: Compressing objects:  90% (65/72)           remote: Compressing objects:  91% (66/72)           remote: Compressing objects:  93% (67/72)           remote: Compressing objects:  94% (68/72)           remote: Compressing objects:  95% (69/72)           remote: Compressing objects:  97% (70/72)           remote: Compressing objects:  98% (71/72)           remote: Compressing objects: 100% (72/72)           remote: Compressing objects: 100% (72/72), done.
(1/172)   Receiving objects:   1% (2/172)   Receiving objects:   2% (4/172)   Receiving objects:   3% (6/172)   Receiving objects:   4% (7/172)   Receiving objects:   5% (9/172)   Receiving objects:   6% (11/172)   Receiving objects:   7% (13/172)   Receiving objects:   8% (14/172)   Receiving objects:   9% (16/172)   Receiving objects:  10% (18/172)   Receiving objects:  11% (19/172)   Receiving objects:  12% (21/172)   Receiving objects:  13% (23/172)   Receiving objects:  14% (25/172)   Receiving objects:  15% (26/172)   Receiving objects:  16% (28/172)   Receiving objects:  17% (30/172)   Receiving objects:  18% (31/172)   Receiving objects:  19% (33/172)   Receiving objects:  20% (35/172)   Receiving objects:  21% (37/172)   Receiving objects:  22% (38/172)   Receiving objects:  23% (40/172)   Receiving objects:  24% (42/172)   remote: Total 172 (delta 87), reused 142 (delta 71)
(43/172)   Receiving objects:  26% (45/172)   Receiving objects:  27% (47/172)   Receiving objects:  28% (49/172)   Receiving objects:  29% (50/172)   Receiving objects:  30% (52/172)   Receiving objects:  31% (54/172)   Receiving objects:  32% (56/172)   Receiving objects:  33% (57/172)   Receiving objects:  34% (59/172)   Receiving objects:  35% (61/172)   Receiving objects:  36% (62/172)   Receiving objects:  37% (64/172)   Receiving objects:  38% (66/172)   Receiving objects:  39% (68/172)   Receiving objects:  40% (69/172)   Receiving objects:  41% (71/172)   Receiving objects:  42% (73/172)   Receiving objects:  43% (74/172)   Receiving objects:  44% (76/172)   Receiving objects:  45% (78/172)   Receiving objects:  46% (80/172)   Receiving objects:  47% (81/172)   Receiving objects:  48% (83/172)   Receiving objects:  49% (85/172)   Receiving objects:  50% (86/172)   Receiving objects:  51% (88/172)   Receiving objects:  52% (90/172)   Receiving objects:  53% (92/172)   Receiving objects:  54% (93/172)   Receiving objects:  55% (95/172)   Receiving objects:  56% (97/172)   Receiving objects:  57% (99/172)   Receiving objects:  58% (100/172)   Receiving objects:  59% (102/172)   Receiving objects:  60% (104/172)   Receiving objects:  61% (105/172)   Receiving objects:  62% (107/172)   Receiving objects:  63% (109/172)   Receiving objects:  64% (111/172)   Receiving objects:  65% (112/172)   Receiving objects:  66% (114/172)   Receiving objects:  67% (116/172)   Receiving objects:  68% (117/172)   Receiving objects:  69% (119/172)   Receiving objects:  70% (121/172)   Receiving objects:  71% (123/172)   Receiving objects:  72% (124/172)   Receiving objects:  73% (126/172)   Receiving objects:  74% (128/172)   Receiving objects:  75% (129/172)   Receiving objects:  76% (131/172)   Receiving objects:  77% (133/172)   Receiving objects:  78% (135/172)   Receiving objects:  79% (136/172)   Receiving objects:  80% (138/172)   Receiving objects:  81% (140/172)   Receiving objects:  82% (142/172)   Receiving objects:  83% (143/172)   Receiving objects:  84% (145/172)   Receiving objects:  85% (147/172)   Receiving objects:  86% (148/172)   Receiving objects:  87% (150/172)   Receiving objects:  88% (152/172)   Receiving objects:  89% (154/172)   Receiving objects:  90% (155/172)   Receiving objects:  91% (157/172)   Receiving objects:  92% (159/172)   Receiving objects:  93% (160/172)   Receiving objects:  94% (162/172)   Receiving objects:  95% (164/172)   Receiving objects:  96% (166/172)   Receiving objects:  97% (167/172)   Receiving objects:  98% (169/172)   Receiving objects:  99% (171/172)   Receiving objects: 100% (172/172)   Receiving objects: 100% (172/172), 37.29 KiB | 2.87 MiB/s, done.
(0/87)   Resolving deltas:   2% (2/87)   Resolving deltas:   3% (3/87)   Resolving deltas:  24% (21/87)   Resolving deltas:  27% (24/87)   Resolving deltas:  48% (42/87)   Resolving deltas:  63% (55/87)   Resolving deltas:  68% (60/87)   Resolving deltas:  70% (61/87)   Resolving deltas:  71% (62/87)   Resolving deltas:  80% (70/87)   Resolving deltas:  81% (71/87)   Resolving deltas:  86% (75/87)   Resolving deltas: 100% (87/87)   Resolving deltas: 100% (87/87), done.
Switched to a new branch 'mes-trucs'
#+end_example

*** second, commit something

**** a non-conflicting change

#+BEGIN_SRC sh
  pwd
  sed -i -es/multicore/manymanycore/g inria/storm.scm
  git add inria/storm.scm
  git commit -m 'Exascale, yay!'
#+END_SRC

#+RESULTS:
: /tmp/guix-hpc
: sh-4.4$ sh-4.4$ [mes-trucs 96c852d] Exascale, yay!
:  1 file changed, 1 insertion(+), 1 deletion(-)


**** and now a conflicting change

#+BEGIN_SRC sh
  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!'
#+END_SRC

#+RESULTS:
: 
: sh-4.4$ [mes-trucs 55a2d56] Update StarPU to 42.3, yay!
:  1 file changed, 1 insertion(+), 1 deletion(-)

*** second, try to merge =master=, fasten your seat belts!

#+BEGIN_SRC sh
  git branch
  git merge master
#+END_SRC

#+RESULTS:
: master
: * mes-trucs
: Auto-merging inria/storm.scm
: CONFLICT (content): Merge conflict in inria/storm.scm
: Automatic merge failed; fix conflicts and then commit the result.

Oh la la!

*** what’s the status?

#+BEGIN_SRC sh
  git status
#+END_SRC

#+BEGIN_SRC emacs-lisp results: none
  (magit-status "/tmp/guix-hpc")
#+END_SRC

#+RESULTS:

*** let’s edit [[/tmp/guix-hpc/inria/storm.scm][the conflict]]

*** once you’re done

#+BEGIN_SRC sh
  git add inria/storm.scm 	# add change to the index
  git merge --continue		# resume merge operation
#+END_SRC

*** view the result

* context: code review/development iteration

** the process: (1) submit, (2) review, (3) goto 1
** iteration history
*** squash intermediate commits because they don’t matter
*** adjust commits and commit logs according to review

* keeping the history linear

** what ‘git merge’ and ‘git pull’ (and ‘git push’ sometimes) do

*** creates a “merge commit”

see the awesome [[http://eagain.net/articles/git-for-computer-scientists/][Git for Computer Scientists]]

[[./git-merge-commit.svg]]

*** show example of linear and non-linear history

  - linear: [[https://github.com/open-mpi/hwloc/commits/master][hwloc]], [[https://git.savannah.gnu.org/cgit/guix.git/log][Guix]]
  - non-linear: [[https://gitlab.inria.fr/solverstack/ScalFMM][ScalFMM]], [[https://github.com/libgit2/libgit2/][libgit2]], [[https://github.com/NixOS/nixpkgs/][NixOS]]

** why should i care?
*** helps understand code evolution
*** helps bisection (‘git bisect’)
*** possibly helps continuous integration
** visualizing the history

  - using =gitk= (which is part of Git)
  - using Magit (in Emacs)
  - using a Web interface (GitLab, cgit, etc.)

** pull/merge requests
*** by default, they introduce merge commits!

** note: sometimes you do need parallel dev branches, that’s fine!

* rebasing

** the Git commit graph

Do not miss [[http://eagain.net/articles/git-for-computer-scientists/][Git for Computer Scientists]]!

[[./git-rebase.svg]]

** 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:

#+BEGIN_SRC sh
  $ git pull --rebase  # fetch remote changes, and rebase on top of them
  $ git push

#+END_SRC

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:

#+BEGIN_SRC sh
    $ git add foo.cpp
    $ git rebase --continue

#+END_SRC

** make ‘git pull’ rebase by default

#+BEGIN_SRC sh
  git config branch.master.rebase true

#+END_SRC

From now on ‘git pull’ will always rebase.  \o/

** tell GitLab to rebase when you accept merge requests

[[./gitlab-merge-request-rebase.png]]

* rebase, “history rewriting”

** Caveat: don’t rebase a published branch!

** tools

**** [[http://github.com/magit/magit/][Magit]] (Emacs)

[[./magit.png]]

**** [[https://github.com/tpope/vim-fugitive][Fugitive]] (Vim)

**** command-line: ‘git rebase -i’ etc.


** amending the last commit of a branch

#+BEGIN_SRC sh
  git add foo			# stage changes
  git commit --amend		# amend the last commit on the branch

#+END_SRC

** 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.

#+BEGIN_SRC sh
  git checkout master
  git pull           # update my copy of 'master'
  git checkout my-feature-branch
  git rebase master  # rebase 'my-feature-branch' on 'master'
#+END_SRC

** 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

** 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!
