#+TITLE: Git workflows, good practices
#+SUBTITLE: An opinionated guide
#+STARTUP: overview hidestars inlineimages
Salut à toi !  Bienvenue dans la bidouille !

Utilise « C-c C-o » (control+c puis control+o) pour suivre les liens
(les trucs soulignés en bleu ci-dessous).

Ce fichier est disponible à http://sed.bordeaux.inria.fr/la-bidouille ou
http://people.bordeaux.inria.fr/lcourtes/git-workflox.org.


* code is a social process

** it’s all about cooperating with others

* optimize for review, bisect, and analysis

** why should i care?

*** make it easier for coworkers to understand what you’re doing
*** facilitate bug hunting with ‘git bisect’
*** make it easier to understand changes *in the future* (‘git annotate’)

** “atomic” commits: one set of related changes at a time

*** when fixing a bug: include fix and test in the commit
*** when adding a feature: include feature + tests + doc

** picking changes for a commit

*** never use “git commit -a”: you may end up committing stuff unwillingly!

=git commit -a= is roughly equivalent to =git add * && git commit=.

*** Git’s staging area (aka. “the index”)

  - =git add foo= adds ‘foo’ to the index (IOW, it stages changes to ‘foo’)
  - =git commit= commits *what’s in the index* (IOW, it commits changes
    that were previously staged)

*** select the right “hunks” for your commit

  - =git add -p= to interactively select hunks
  - =S= in Magit to stage a given hunk

*** stash unrelated changes away

#+BEGIN_SRC sh
  git stash			# "stashes away" working-tree changes
  # hack on stuff...
  git commit			# commit the things
  git stash pop			# reinstate stashed changes
#+END_SRC

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

[[./magit.png]]

**** [[https://github.com/tpope/vim-fugitive][Fugitive]] (Vim)
**** at the command line: pretty hard inconvenient

** comments usually belong in the code, not in the commit log

** keep related changes in a branch (possibly a series of several commits)

*** example: feature branch, doc branch

* submitting code

** submit the whole set of related changes at once

Could be one commit (e.g., bug fix), or could be a whole series (e.g.,
add feature X).

** check the submission checklist (if there’s one)

  - [[https://github.com/NixOS/nixpkgs/pull/22506][example of a checklist on GitHub]]

** rebase your submission branch on the target branch

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

See [[*rebasing][this]] for a discussion of rebasing.

** by email

*** step 0: set your name and email address

#+BEGIN_SRC sh
  git config --global user.email
  git config --global user.name
#+END_SRC

*** step 1: ‘git format-patch’

#+BEGIN_SRC sh
  git checkout wip-cool-feature
  git format-patch master
#+END_SRC

or:

#+BEGIN_SRC sh
  git format-patch --cover-letter
#+END_SRC

*** step 2: ‘git send-email’

#+BEGIN_SRC sh
  git send-email 0*.patch

#+END_SRC

** by pushing code somewhere

#+BEGIN_SRC sh
  git push wip-foo my-remote-server
#+END_SRC

** on GitLab

*** create a “fork”

example: [[https://gitlab.inria.fr/solverstack/chameleon/forks][Chameleon forks]]

*** create a topic-specific branch

example: [[https://gitlab.inria.fr/solverstack/chameleon/merge_requests/11][‘fpruvost:update_texinfo’ branch]]

*** create a merge request

example: [[https://gitlab.inria.fr/solverstack/chameleon/merge_requests/15][Chameleon merge request]]

* reviewing code

** stay focused: comment on the actual changes
*** resist the temptation to discuss wider changes
*** don’t require submitters to fix things that were already broken
** rely on automation for the boring part of the review
*** code style checkers, etc.
** iterating
*** 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

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

#+END_SRC

**** how to squash/rewrite commits?
***** command line: ‘git rebase -i’
***** Magit

** reviewing tools
*** email!  :-)

examples:

  - [[http://lists.nongnu.org/archive/html/qemu-devel/2017-02/threads.html][QEMU]]
  - [[https://lkml.org/lkml/2017/2/7][the kernel Linux]]

*** GitLab
*** Gerrit
*** Phabricator

https://forge.softwareheritage.org/D116

*** Trac
*** discussion of email vs. web tools

  - [[https://lwn.net/Articles/702177/][Why kernel development still uses email]]

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

*** show example of linear and non-linear history
** 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
  - using a Web interface (GitLab, cgit, etc.)

** pull/merge requests
*** by default, they introduce merge commits!
** rebasing
*** the Git commit graph

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

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

*** rebasing a branch on master

Before submitting, rebase your branch on top of ‘master’.
See [[*rebase your submission branch on the target branch][details here]].

