5
votes

Git garde-t-il une trace des conflits de fusion passés?

J'aimerais regarder l'historique du référentiel et voir quels types de conflits de fusion se sont produits dans le passé.

J'ai essayé d'utiliser git log --merges mais cela semble juste montrer des fusions réussies.


1 commentaires

Je ne pense pas que ce soit le cas à moins que vous n'activiez rerere .


4 Réponses :


2
votes

Je pense que vous pourriez bénéficier de git-rerere en combinaison avec les questions précédentes sur l'entraînement:

Je pense que l'emplacement de stockage réel est dans .git / rr-cache , mais je n'ai jamais cherché et je ne sais pas ce qu'il y a dedans.


0 commentaires

4
votes

Git n'enregistre pas les conflits de fusion, sauf si vous avez activé la rerere, mais il enregistre la plupart des informations nécessaires pour les recréer. Vous pouvez écrire un script pour recréer les conflits de fusion, avec quelques mises en garde ... Git n'enregistre pas la stratégie de fusion que vous avez utilisée pour résoudre une fusion, vous devrez donc espérer que les stratégies par défaut sont des choix judicieux, ou faire quelques ajustements pour que cela fonctionne sur votre dépôt.

Comment ça marche

Vous pouvez énumérer les fusions avec rev-list:

git merge --abort

Ceci est préférable à git log , car la sortie est adaptée à l'analyse par un script. Cela produira une liste de commits de fusion, un par ligne. Le commit enfant est le premier hachage et les hachages restants sont les parents. Par exemple,

git status --porcelain

Ici, la fusion est entre 20af et 2d77.

Découvrez le premier parent, en tête détachée:

XXX

Ensuite, fusionnez les parents restants:

git merge -q --no-commit --no-ff 2d77896f5fcc1a9b09f4f099aa6e945e8da86410

Le code d'état de merge sera 1 s'il y a des conflits , que vous pouvez examiner. S'il y a un conflit de fusion, vous verrez les fichiers avec UU dans l'état porcelaine:

git checkout -q --detach 20af81cf6388026ecf0de4eec8783e7a38905ccd

Vous pouvez alors abandonner la fusion pour réinitialiser à un indiquez où vous pouvez travailler avec le dépôt:

28171e725cc93e8cb85194931e7138c31f980a43 20af81cf6388026ecf0de4eec8783e7a38905ccd 2d77896f5fcc1a9b09f4f099aa6e945e8da86410

Script

J'ai transformé cela en un script comme une démo. Le script doit être exécuté sur un référentiel vierge , car il exécutera un tas de commandes git checkout et git merge .

https://gist.github.com/depp/f1838cf4559f9cde74b9d3052b8abb0

p> Le script réessayera chaque fusion dans l'historique en utilisant la stratégie par défaut, et signalera les fichiers en conflit.

Si vous le souhaitez, vous pouvez facilement étendre le script pour copier les fichiers en conflit afin que vous puissiez consulter le conflits.


2 commentaires

@crashmstr: Dans Git, la copie de travail est (généralement) elle-même également un référentiel. Cela ne fonctionnera pas dans un dépôt nu et vous ne devriez pas avoir de modifications locales non validées.


Un script très similaire est rerere-train qui est disponible dans le dépôt git.git lui-même: github.com/git/git/blob/master/contrib/rerere-train.sh



1
votes

Pas facilement ... mais vous pouvez lancer un script si vous en avez besoin ...

Vous pouvez utiliser git log pour trouver tous les merge-commits - en supposant que vous ayez laissé le message automatique en place, ou utilisez un message qui est (espérons-le) toujours le même. Par exemple:

git log --all --oneline --graph --decorate produit une arborescence décente du dépôt - par exemple:

     both modified:   testfile1.txt     <---- THIS FILE IS A CONFLICT

Mais pour le script, utilisez simplement git log --oneline --all :

a1a9bde
bec65ad

Ou obtenez simplement la liste de hachage : git log --oneline --all | grep "Fusionner la branche" | awk '{print $ 1}' :

a1a9bde Merge branch 'test' into TESTER      <----- LETS LOOK AT THIS MERGE...
eb9ab80 updated
2ff3965 updated
bec65ad Merge branch 'master' of d:\software\sandpit\git-test
8a73cd1 updated test1
58080f2 new file
819226c new file
e122cc6 file for merge back to master
49acb0b file added in branch
a262470 yet another file
12af0b0 s

mise à jour 1

ou comme Dietrich Epp (presque) utilisation suggérée git rev-list --min-parents = 2 a1a9bde - cela donne le hash complet de tout commit avec 2 parents - gentil Dietrich Epp code >!

mise à jour 1 - fin

Maintenant, parcourez ces hachages, par exemple à partir d'ici en utilisant le premier: a1a9bde

Vous pouvez obtenir le hachage parent comme: git show --format = "% P" 595bff6 - ceci yeilds:

eb9ab8029e6951f68a9c1008bb8611444d31528d 2ff3965b9aa1e6c49c82127e5f08199796a40780

Vous pouvez maintenant exécuter une simulation de fusion par:

  • Checkout the first hash: git checkout eb9ab8029e6951f68a9c1008bb8611444d31528d -B merge_test - ceci vérifie le premier hachage sur une branche appelée merge_test (et remplace toute branche précédente de le même nom)

  • fusionner le deuxième hachage (essai à sec): git merge --no-commit --no-ff 2ff3965b9aa1e6c49c82127e5f08199796a40780

  • Utilisez git status | grep "les deux modifiés" pour voir les conflits - donne:
*   a1a9bde (HEAD -> TESTER) Merge branch 'test' into TESTER
|\
| * 2ff3965 (test) updated
| * 12af0b0 s
* | eb9ab80 updated
* |   bec65ad (master) Merge branch 'master' of d:\software\sandpit\git-test
|\ \
| * \   595bff6 Merge branch 'master' of d:\software\gitRepos\git-test
| |\ \
| | * | 77d69c7 new file
| | |/
   :
  • Maintenant, faites ce que vous devez faire, puis enfin ranger avec git merge --abort

Donc de toute façon - c'est un peu douloureux, mais tout cela peut être scripté assez facilement, j'ai fourni les commandes pour le faire mais je n'ai pas la motivation d'écrire le script ...: o


2 commentaires

Vous voudrez utiliser git rev-parse --min-parents = 2 au lieu de git log | grep , car tous les validations de fusion n'auront pas le même format.


@DietrichEpp Belle entrée:) - bien que cela me laisse perplexe pendant un moment - je pense que vous vouliez dire rev-list - a ajouté une mise à jour :))



1
votes

Pour un premier aperçu rapide, vous pouvez utiliser:

-c
   With this option, diff output for a merge commit shows the
   differences from each of the parents to the merge result
   simultaneously instead of showing pairwise diff between a parent
   and the result one at a time. Furthermore, it lists only files
   which were modified from all parents.

--cc
   This flag implies the -c option and further compresses the patch
   output by omitting uninteresting hunks whose contents in the
   parents have only two variants and the merge result picks one of
   them without modification.

L'option --cc est (à partir de git help log ):

git log --merges --cc --all

Cela montrera les conflits mais - AFAICT - un peu plus sur les "conflits proches".


1 commentaires

Beau! Avec cela, vous pouvez partir à la recherche de conflits et trouver des conflits à examiner (en recréant le conflit et en comparant le résultat de la fusion).