86 votes

Est-il possible d'exclure des commits spécifiques lors d'une fusion git?

Supposons que je souhaite fusionner d'une branche de version vers la branche principale et que certains éléments de la validation soient inclus dans la branche de version, mais que je ne souhaite pas les inclure dans la branche principale. Existe-t-il un moyen de procéder à la fusion afin qu’un ou plusieurs de ces commits ne soient pas fusionnés?

Ma stratégie jusqu'ici consiste à effectuer les opérations suivantes (en maître):

 git merge --no-commit release-branch
# Resolve conflicts and apply reverse patch of the commits that I don't want included
git commit # Edit commit message so that it lists the commits that have been reverse-patched
 

Y a-t-il une meilleure manière de faire cela?

123voto

fcurella Points 1145

J'ai trouvé une solution qui fonctionne pour moi dans le Pro Git livre.

Disons que vous voulez exclure le fichier config.php.

Sur la branche d'Un:

  1. Créez un fichier nommé .gitattributes dans le même dir, avec cette ligne: config.php merge=ours. Cela indique à git que la stratégie à utiliser lors de la fusion du fichier. Dans ce cas, gardez toujours votre version, c'est à dire. la version sur la branche que vous fusionnent.

  2. Ajouter l' .gitattributes le fichier et de s'engager

Sur la branche B: répétez les étapes 1-2

Essayez la fusion de maintenant. Votre fichier doit être laissé intact.

52voto

Dustin Points 35205

Créez une nouvelle branche, rebassez la branche de manière interactive et supprimez les validations que vous ne voulez pas, puis fusionnez-la.

Vous ne pouvez pas supprimer des modifications du milieu d’une branche sans répéter l’action, mais ce qui est bien se produira lorsqu’il observera les mêmes modifications lors d’une fusion ultérieure (par exemple, à partir d’une sélection sélective ou autre).

27voto

Tobias Schulte Points 1905

Si vous avez un support de la branche où vous corriger les bugs et à construire de nouvelles versions. Sur le master que vous avez la version suivante, où vous avez également la construction de nouvelles versions régulièrement.

Chaque fois que vous créez une nouvelle version, vous changer la version dans le fichier, s'engager sur ce nouveau fichier, créer une balise et de pousser. Maintenant fusionne de soutien à maître aura toujours des conflits dans le fichier contenant les informations de version.

Si le fichier contenant les informations de version seulement contient les informations de version, vous pouvez aller avec la réponse de fcurella. Mais si elle ne fait peut également contenir fusionnables informations (pom.xml, gradle.propriétés, MANIFESTE.MF, ...), vous devez effectuer une certaine action supplémentaire.

Prenons l'exemple suivant

      C---D*---E---F* support
     /
A---B---G---H*---I master

où s'engage avec des étoiles contiennent seulement les changements dus à des changements de version qui devrait être ignoré lors de la fusion.

Pour fusionner soutien en maître sans fusion-conflits dus à la version construit, vous pouvez effectuer une des opérations suivantes:

Plusieurs de fusion s'engage

git checkout master
git merge C
git merge D -s ours
git merge E
git merge F -s ours

Avec l' -s ours argument que nous disons git pour enregistrer uniquement une fusion sans modifier l'espace de travail. Ceci est comparable à l' --record-only option de svn.

Ci-dessus entraînera la mise en page suivante

      -------------C---D*---E---F* support
     /              \   \    \   \
A---B---G---H*---I---J---K----L---M master

Une fusion valider à l'aide de cherry-pick

git checkout master
git merge support -s ours --no-commit
git cherry-pick C E --no-commit
git commit -m 'merged support into master'

d'abord nous sommes au début d'une fusion, mais seulement que nous la fusion, sans modifier l'espace de travail et sans faire la fusion s'engager. Puis nous sommes cherry-picking les commits de fusion, de nouveau sans s'engager. Enfin, nous nous engageons à la fusion.

Ci-dessus entraînera la mise en page suivante

      C---D*---E---F* support
     /              \
A---B---G---H*---I---J master

On peut même automatiser le cherry-picking.

git checkout master
git merge support -s ours --no-commit
for id in `git log support --reverse --not HEAD --format="%H [%an] %s" |
  grep -v "bump version" |
  sed "s/\(\w*\)\s.*/\1/g"`
do
  git cherry-pick --no-commit $id
done
git commit -m 'merged support into master'

4voto

user43563 Points 261

La raison pour laquelle cela ne peut pas être fait directement est que chaque commit contient des liens vers les commits parents (généralement un seul mais plusieurs pour les fusions). Ainsi, si vous avez un commit (par sa somme SHA1), l'historique complet est également fixé, car les parents contiennent également des liens avec leurs parents, etc. Donc, la seule façon de laisser de côté les correctifs dans l’histoire est d’en écrire un nouveau. git rebase -i sur une branche nouvellement créée est probablement le moyen le plus simple d'y parvenir.

3voto

Kuznero Points 36

Il est également possible de modifier le fichier .git / info / attributs et de le conserver dans le dossier .git au lieu d’ajouter des fichiers .gitattribute, ce qui nécessitera leur ajout éventuel au contrôle de source.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X