Une option pratique de git que l'on oublie souvent : -p
ou --patch
Elle permet de réaliser des commits cohérents et atomiques en fournissant la possibilité de choisir les fichiers ou parties de fichiers que l'on souhaite incorporer à un commit. Cette option fait partie des commandes du mode interactif de git que l'on ne détaillera pas dans cet article. Vous trouverez plus d'information à ce sujet ici.
Commençons par un exemple simple, notre projet est constitué du fichier test.c suivant:
/* old code 1 */ /* old code 2 */ /* old code 3 */
Nous venons de travailler sur l'ajout d'une fonctionnalité et, dans le même temps, nous avons corrigé un bug découvert par un collègue sur l'ancien code. N'ayant pas eu le temps de créer une autre branche pour la correction du bug nous nous retrouvons avec un ensemble de modifications touchant à deux fonctionnalités différentes dans le même fichier. Voici ce que donne la commande ‘diff
’ :
$ git diff diff --git a/test.c b/test.c index 3ec7db0..d87fa2a 100644 --- a/test.c +++ b/test.c @@ -1,6 +1,12 @@ +/* new feature 1 */ + /* old code 1 */ +/* bug fix */ + /* old code 2 */ +/* new feature 2 */ + /* old code 3 */
Nous souhaiterions maintenant créer deux commits distincts pour que ceux qui viendront modifier le code par la suite puissent plus facilement comprendre ce qui a été fait :
- Le commit ajoutant la nouvelle fonctionnalité
- Le commit corrigeant le bug
C'est là qu'intervient l'option --patch
(ou -p
). Utilisée conjointement avec la commande ‘add
’ nous allons pouvoir indexer les modifications souhaitées.
$ git add -p test.c diff --git a/test.c b/test.c index 3ec7db0..d87fa2a 100644 --- a/test.c +++ b/test.c @@ -1,6 +1,12 @@ +/* new feature 1 */ + /* old code 1 */ +/* bug fix */ + /* old code 2 */ +/* new feature 2 */ + /* old code 3 */ Stage this hunk [y,n,q,a,d,/,s,e,?]?
Git nous remontre les modifications qui ont eu lieu sur le fichier puis nous demande si l'on souhaite indexer ces modifications. ‘?
’ permet d'avoir accès à plus d'explications :
$ Stage this hunk [y,n,q,a,d,/,s,e,?]? ? y - stage this hunk n - do not stage this hunk q - quit; do not stage this hunk nor any of the remaining ones a - stage this hunk and all later hunks in the file d - do not stage this hunk nor any of the later hunks in the file g - select a hunk to go to / - search for a hunk matching the given regex j - leave this hunk undecided, see next undecided hunk J - leave this hunk undecided, see next hunk k - leave this hunk undecided, see previous undecided hunk K - leave this hunk undecided, see previous hunk s - split the current hunk into smaller hunks e - manually edit the current hunk ? - print help
Commençons par créer le commit qui ajoute la nouvelle fonctionnalité. Nous allons ici utiliser la commande ‘s
’ pour diviser le groupe de modifications en plusieurs groupes plus petits.
Stage this hunk [y,n,q,a,d,/,s,e,?]? s Split into 3 hunks. @@ -1,2 +1,4 @@ +/* new feature 1 */ + /* old code 1 */
Puis nous allons indexer ce premier groupe de modifications en répondant par l'affirmative ‘y
’.
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]? y @@ -1,4 +3,6 @@ /* old code 1 */ +/* bug fix */ + /* old code 2 */
Git passe ensuite au groupe de modifications suivant. Celui-ci ne correspond pas à l'ajout de la nouvelle fonctionnalité, nous ne l'indexons donc pas pour l'instant (‘n
’).
Stage this hunk [y,n,q,a,d,/,K,j,J,g,e,?]? n @@ -3,4 +7,6 @@ /* old code 2 */ +/* new feature 2 */ + /* old code 3 */ Stage this hunk [y,n,q,a,d,/,K,g,e,?]? y
Nous indexons par contre le troisième bloc correspondant à l'ajout de la nouvelle fonctionnalité. Vérifions maintenant ce qui a été indexé :
$ git diff --staged diff --git a/test.c b/test.c index 3ec7db0..5bc8d01 100644 --- a/test.c +++ b/test.c @@ -1,6 +1,10 @@ +/* new feature 1 */ + /* old code 1 */ /* old code 2 */ +/* new feature 2 */ + /* old code 3 */
Toutes les modifications correspondant à l'ajout de la nouvelle fonctionnalité sont dans l'index, nous pouvons maintenant faire le premier commit.
$ git commit
Il reste ensuite à faire le commit pour la correction du bug:
$ git diff diff --git a/test.c b/test.c index 5bc8d01..d87fa2a 100644 --- a/test.c +++ b/test.c @@ -2,6 +2,8 @@ /* old code 1 */ +/* bug fix */ + /* old code 2 */ /* new feature 2 */ $ git add test.c $ git commit
Nous nous retrouvons finalement bien avec deux commits distincts, le premier correspondant à l'ajout de la fonctionnalité et le second corrigeant le bug.
L'option -p
peut également être utilisée avec les commandes git suivantes:
- git reset
- git checkout
- git stash