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.
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
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!
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
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.
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.