Est-ce mal de pousser des branches de force de poussée?

11

Lorsque je travaille sur une branche de fonctionnalité, j'ai tendance à vouloir nettoyer les validations dans la branche à l'aide d'une rebase interactive avant que mon travail ne soit examiné et intégré dans la branche principale.

Pendant le développement de la fonctionnalité, je souhaite transférer mon travail intermédiaire vers le référentiel distant comme mesure de sauvegarde. C'est-à-dire lorsque mon disque dur tombe en panne, je ne veux pas que toute ma branche de fonctionnalités soit perdue.

Cependant, cela conduit au fait que je dois souvent faire un git push --forceau référentiel distant après un rebase, une action qui est généralement mal vue. Ou comme le dit la page github liée:

Étant donné que la modification de votre historique de validation peut rendre les choses difficiles pour tous les autres utilisateurs du référentiel, il est considéré comme une mauvaise pratique de rebaser les validations lorsque vous avez déjà poussé vers un référentiel.

Existe-t-il une politique (généralement acceptée) qui résout ce conflit?

Pourquoi ce n'est pas un double de Est-ce que le git "Golden Rule of Rebasing" est si essentiel?

Ma question ici demande une politique pour résoudre le conflit entre vouloir sauvegarder votre travail dans le référentiel distant et rebaser votre travail , tandis que l'autre question essaie de nier qu'il y a un conflit et demande pourquoi certaines personnes pensent que le conflit existe, et demande donc pourquoi "il est essentiel" de ne pas pousser les rebases de force?

Chiel ten Brinke
la source
1
@gbjbaanb si vous effectuez des validations WIP, un rebase est très utile pour éviter d'avoir de nombreuses validations pour une seule journée de travail. Je fais souvent des commits pour de petits changements juste pour avoir une option "Annuler à un état dont je me souviens" si nécessaire - la plupart d'entre eux ne sont pas pertinents / bruit pour l'historique principal du dépôt (c'est pourquoi le rebase est si utile).
enderland
1
@gbjbaanb C'est une question d'opinion, je pense. De nombreuses équipes utilisent une stratégie de rebasage pour garder leur historique propre.
Chiel ten Brinke
1
@enderland tout le monde veut une jolie histoire, c'est toujours la mauvaise chose (et dangereuse) à faire comme le montre le lien. Torvalds n'aurait jamais dû le mettre dedans, il aurait dû permettre que les commits soient "compressés" sur l'affichage.
gbjbaanb
1
@gbjbaanb mais ... il ne l'a pas fait, et nous devons donc travailler avec ce que nous avons. Pour moi, il est beaucoup plus utile d'avoir un seul commit sur la branche master au lieu de 30+ commits individuels et incrémentiels de chaque branche de fonctionnalité. Mais tout le monde aura un workflow différent, je suppose ...
enderland

Réponses:

5

La question clé à vous poser:

  • Conservez-vous votre branche distante après avoir fusionné à nouveau dans master?

Si vous supprimez votre branche de fonctionnalité distante après la fusion dans Master, vous perdez déjà l'historique. En supposant que vous écrasiez / rebasiez la branche avant de faire votre fusion / RP, vous perdiez cet historique. Tout ce que votre poussée de force fait dans ce cas vous permet d'utiliser github comme sauvegarde.

La situation dans laquelle vous souhaitez conserver l'historique et ne pas forcer la poussée est si votre branche distante persiste après avoir été fusionnée et n'existe pas seulement pendant une période temporaire.

Je suppose que vous demandez si je garderais la branche non révisée? Non, l'AFAIC. Pourtant, le forcer à pousser pourrait théoriquement entraîner la perte de commits d'autres utilisateurs qui ont poussé vers la même branche

Il semble que vous ayez plusieurs personnes poussant simultanément vers cette branche. Cela signifie que vous vous souciez de l'historique de la branche.

Ce que vous pourriez faire à la place pour votre travail intermédiaire est de créer un fork de cette branche. Vous pouvez pousser à cela, puis rebaser toutes vos validations en une seule validation avant la fusion, donc lorsque vous les fusionnez dans votre branche de fonctionnalité, vous n'avez qu'une seule validation (avec l'historique rebasé de votre branche entière).

enderland
la source
"Gardez-vous votre branche distante après avoir fusionné à nouveau dans le maître?" Je suppose que vous demandez si je garderais la branche non révisée? Non, l'AFAIC. Pourtant, le forçage forcé pourrait théoriquement entraîner la perte de commits d'autres utilisateurs qui ont poussé vers la même branche.
Chiel ten Brinke
@ChieltenBrinke J'ai édité un peu à ce sujet. FYI
enderland
Je pense que le forking comme mesure pour éviter de détruire les commits lors du push forcing est en fait une très bonne suggestion. Mais AFAIK, ce n'est pas vraiment un concept git, et vous avez besoin d'un wrapper de service pour le faire facilement (comme github). Ai-je raison à ce sujet? Ou peut-être que je prends votre utilisation du terme "fourche" pour créer simplement une branche distincte?
Chiel ten Brinke
@ChieltenBrinke vous pouvez bien accomplir la même chose de différentes manières. Si votre branche de fonctionnalité se trouve sur le référentiel distant, vous pouvez bifurquer le dépôt et avoir votre version de cette branche. Et puis fusionnez cette branche dans votre branche distante après la validation de l'écrasement. Ou vous pouvez simplement créer une branche locale différente (peut-être featurebranch-local) puis faire un développement actif sur cette branche, avec autant de validations que vous le souhaitez. Une fois que vous souhaitez fusionner, écrasez ces validations, puis fusionnez-les dans la fonctionnalité. Fondamentalement, il suffit de faire du développement dans une branche temporaire réelle, puis de compresser / fusionner dans votre fonctionnalité.
enderland
En supposant que bifurquer un repo est hors option car on n'utilise pas github, nous travaillerions avec une develop-featurebranche "privée" . Bien sûr, le caractère privé est purement conventionnel et n'est imposé par rien, mais peut faire partie d'une politique, surtout si certaines conventions de dénomination de branche sont introduites pour cela. (Peut-être que je suis trop anxieux en ce moment, peut-être pas :) La combinaison avec --force-with-leasene peut pas faire de mal, mais ne devrait pas être invoquée, comme indiqué dans mon autre article.
Chiel ten Brinke
3

J'énumère ici quelques possibilités qui me viennent à l'esprit.

Toujours rebaser sur une nouvelle branche

Lorsque vous some-featureavez une branche en désordre , rebasez-la sur une nouvelle branche. Par exemple

$ git checkout -b some-feature-rebase
$ git rebase -i master # etc..

Ensuite, ont some-feature-rebaserévisé et intégré.

Problème: Un gros inconvénient est que, à proprement parler, vous avez besoin d'une nouvelle branche pour chaque rebase. (Vous pouvez avoir plusieurs rebases si vous apportez des modifications après une révision de code, par exemple)

Utilisation git push --force-with-lease

Je viens d'apprendre l' git push --force-with-leasealternative àgit push --force laquelle

refuse de mettre à jour une succursale à moins que ce soit l'état que nous attendons; c'est-à-dire que personne n'a mis à jour la branche en amont.

Problème : cela semble améliorer directement la situation où nous utilisons juste --force, mais il y a toujours quelques mises en garde, notamment lorsque je fais un git fetchau lieu d'un git pull, qui met à jour nos branches locales en amont, --force-with-leaseen pensant qu'aucune modification non fusionnée n'a été apportée sur la télécommande branche.

Chiel ten Brinke
la source