Git fusionne squash à plusieurs reprises

j'essaie d'avoir deux branches avec des fichiers binaires dans git un "développement" et un "stable". La Direction générale du développement peut avoir plusieurs modifications de ces fichiers avant que je ne souhaite les "libérer" dans la Direction générale stable (et la Direction générale stable a ces fichiers renommés, si cela est pertinent).

je pourrais faire une fusion normale, cela fonctionne bien, mais préserve trop d'histoire - en tirant la branche "stable", toutes les commits intermédiaires de la branche "développement" sont tiré aussi bien (parce qu'ils parent s'engage). Mais nous parlons de fichiers binaires qui n'ont pas de stratégie de fusion sensée (sauf leur/la nôtre), de sorte que l'histoire réelle des fichiers sur la branche de développement est inutile. Quand je tire la branche "stable", je reçois ceci:

          X-------------------G stable
         /                   /
    a---b---c---d---e---f---g development

parce que G a un parent dans la branche développement, j'obtiens toute l'histoire de la branche développement (objets de données pour c, D, e, f et g) dans mon dépôt, ce qui ne m'intéresse pas (X est le même que b, avec quelques renommage de fichiers).

donc j'ai essayé de git merge --squash passe de la branche développement à la branche stable. La première fusion et commit se sont bien passées, les résultats ont été comme prévu (log de changement nice dans le message de commit, aucune relation avec la branche de développement):

          X-------------------G stable
         /                   
    a---b---c---d---e---f---g development

après avoir tiré cette branche stable écrasée, j'obtiens ceci dans mon dépôt, qui est ce que je veux:

a---b---X---G

But la seconde Fusion a échoué (parce que git n'avait aucun moyen de savoir à quel point j'ai déjà fusionné et je me suis embrouillé).

  • est-il possible d'enregistrer d'une manière ou d'une autre la fusion, sans produire une" commit de fusion " avec deux parents?
  • ou, est-il possible de dire à git de ne fusionner qu'une certaine" plage " de révisions, comme dans SVN?
  • ou, est-il possible de faire une fusion normale sans avoir à télécharger tous les Ref de l'autre branche en tirant?
  • ou dois-je fournir un pilote de fusion personnalisé pour les fichiers en question, qui renomment simplement" leur "version en" notre", résolvant ainsi les conflits? J'ai toujours peur que --squash essaie toujours de fusionner toute l'histoire, jusqu'au parent commun, résolvant seulement la moitié de mon problème.

mise à Jour: rebasage

si je comprends le rebasement correctement, je finirai avec ceci:

                              X stable
                             /
    a---b---c---d---e---f---g development

ce qui me donne toutes les données qui ne m'intéressent pas (c, D, e, f) et en prime, je vais perdre l'information que b était une version stable dans la branche.

chaque révision de développement ajoute environ 5 Mo à la taille du dépôt (et le réemballage de l'ensemble du dossier ne le réduit que d'environ 10%), la branche "stable" vient presque gratuitement (les données sont déjà là). Je veux tirer une seule nouvelle révision de la branche stable pour tirer seulement la nouvelle 5 Mo, mais à la place mise à jour de X à G télécharge 25 Mo, parce que je ne suis pas en mesure de dire que je ne me soucie pas du contenu de c, d, e et F.

24
demandé sur Ken Williams 2009-09-23 12:12:41

5 réponses

commençant par

      X stable
     /                   
a---b---c---d---e---f---g development

vous pouvez utiliser les étapes suivantes pour copier le dernier commit de votre branche de développement vers votre branche stable:

git checkout development@{0}  # get working tree from "development", detach HEAD
git reset --soft stable  # reposition detached HEAD on "stable"
git commit  # enter the appropriate commit message
git branch temp  # create a temporary branch "temp" at HEAD
git checkout temp  # get on the new temporary branch
git branch -M stable  # rename "temp" to "stable"

pour finir avec:

      X-------------------G stable
     /                   
a---b---c---d---e---f---g development

si vous continuez à travailler sur le "développement", par exemple,

      X-------------------G stable
     /                   
a---b---c---d---e---f---g---h---i---j development

vous pouvez répéter les mêmes commandes git que ci-dessus et vous finirez avec:

      X-------------------G-----------J stable
     /                   
a---b---c---d---e---f---g---h---i---j development
23
répondu pvillela 2010-12-19 04:40:45

Ce n'est pas le bon endroit pour utiliser merge --squash . Un bon endroit pour l'utiliser est dans une branche throwaway, que vous allez fusionner dans votre branche principale et ensuite se débarrasser de. Tout le développement fait dans la branche de thème est montré comme un commit dans la branche principale. Dans votre situation, vous devriez fusionner de la branche de développement normalement, puis utiliser git-rebase --interactive pour écraser les propagations que vous voulez.

est-il possible d'une façon ou d'une autre enregistrer la fusion, sans produire une "commit de fusion" avec deux parents?

si je comprends bien la question, non. absolument pas .

est-il possible de dire à git de ne fusionner qu'un certain" intervalle " de révisions, comme dans SVN?

Oui. git merge [commit hash]

ou, est-il possible de faire une fusion normale sans avoir à télécharger tous les Ref de l'autre branche en tirant?

voir la réponse à la question précédente.

ou dois-je fournir un pilote de fusion personnalisé pour les fichiers en question, qui renomment simplement" leur "version en" notre", résolvant ainsi les conflits? Je suis toujours peur que --squash va toujours essayer d' fusionner toute l'histoire, jusqu'au parent commun, résolvant seulement la moitié de mon problème.

Non! N'utilisez simplement pas git merge --squash . Ce n'est pas le bon endroit pour l'utiliser!

7
répondu artagnon 2017-10-10 11:53:55

vous pouvez utiliser git rebase -i (mode interactif) pour sqash tous vos changements, il suffit de changer les lignes à m ou meld (mise à jour: pour les nouvelles versions de Git type s ou squash )

vous aurez qu'un seul commit que vous pouvez fusionner. si vous voulez que chaque pas soit réservé, vous devez créer une autre branche sur votre branche de piratage avant de faire le rebase, cela peut être fait avec git branch small-dirty-changes-i-don’t-want-anybody-to-see

tout cela a à faire avant de tenter de fusionner étape par étape;:

# on branch "hacking": hack commit hack commit hack commit

# create a reference to your history
$ git branch dirty-history

# sqash your commits by setting all lines to "meld"
$ git rebase -i

# checkout master or the branch you want to merge to
$ git checkout master

# merge your squashed commit
$ git merge hacking
# or: $ git pull hacking
4
répondu knittl 2017-12-03 17:22:04

Le top voté réponse effectivement diff la stabilité et le développement de branches et de toutes les modifications manquant dans l'écurie comme un commit. Il y a une autre façon de le faire:

$ git checkout stable 
$ git diff stable development | git apply --index -   
$ git commit

avant de vous engager, vous pouvez consulter les fichiers mis en scène. Si vous voulez annuler le processus après avoir appliqué la diff, vous pouvez simplement utiliser des commandes de base pour supprimer les modifications de l'index et du répertoire de travail.

$ git reset --hard

Vous pouvez répéter le processus plusieurs fois, puisque vous sont effectivement juste diff-ing les extrémités des deux branches à chaque fois que vous avez besoin de fusionner.

notez qu'il y a ici une hypothèse qui s'applique aussi à l'autre réponse: il n'y a pas de commits dans la branche stable autres que ceux qui proviennent de la branche développement . Si la même ligne était changée indépendamment dans les deux branches, contrairement à une fusion régulière, cette approche pas vous donner un conflit. Au lieu de cela, il supplanterait simplement les changements dans la branche stable avec ceux en développement.

si vous êtes préoccupé par cela, chaque fois que vous vous engagez dans stable, vous pouvez mettre la plage de hash de la propagation fusionnée dans le message de propagation. Comme ça, tu auras un casier, si tu as besoin de revenir en arrière.

1
répondu Raghu Dodda 2017-05-23 11:46:33

je suis nouveau à git, mais il semble que --squash est ce que vous voulez, vous avez juste besoin de gérer la branche différemment.

$ git merge --squash development
$ git branch -d development
$ git checkout -b development
# continue work on development branch

cela tronquerait essentiellement l'histoire de la branche de développement, et la prochaine fusion ne serait que ce que vous vouliez. En regardant la page de manuel, il semble que git branch -f development pourrait faire la même chose que supprimer et recréer la branche.

Comme je l'ai dit, je suis assez nouveau à git, donc j'aimerais quelques commentaires sur ce idée.

-1
répondu Glenn Moss 2011-02-01 14:50:08