web-dev-qa-db-fra.com

git Push --force-with-lease vs. --force

J'essaie de comprendre la différence entre

git Push -f

et

git Push --force-with-lease

je suppose que ce dernier ne fait que pousser vers la télécommande si la télécommande n'a pas de commet que la branche locale n'a pas?

S'il y a un meilleur moyen de formuler la question, lmk, mais j'espère que c'est clair.

52
Alexander Mills

force écrase une branche distante avec votre branche locale.

--force-with-lease est une option plus sûre qui ne remplacera aucun travail sur la branche distante si plusieurs validations ont été ajoutées à la branche distante (par un autre membre de l'équipe ou un collègue ou ce que vous avez). Cela garantit que vous n'écrasez pas le travail de quelqu'un d'autre en poussant de force.

Je pense que votre idée générale autour de la commande est correcte. Si la branche distante a la même valeur que la branche distante sur votre ordinateur local, vous écraserez Remote. S'il n'a pas la même valeur, il indique une modification apportée à la branche distante par une autre personne pendant que vous travailliez sur votre code et n'écrasera donc aucun code. Évidemment, s'il y a des commits supplémentaires dans remote, les valeurs ne seront pas les mêmes.

Je pense simplement à --force-with-lease comme à l'option à utiliser lorsque je veux m'assurer de ne pas écraser le code de mes coéquipiers. De nombreuses équipes de mon entreprise utilisent --force-with-lease comme option par défaut pour une sécurité intégrée. C'est inutile dans la plupart des cas, mais cela vous évitera beaucoup de maux de tête si vous écrasez quelque chose qu'une autre personne a contribué à distance.

Je suis sûr que vous avez consulté la documentation, mais il pourrait y avoir une explication plus verbeuse ici:

https://git-scm.com/docs/git-Push

27
chevybow

git Push --force est destructif car il écrase de manière inconditionnelle le référentiel distant avec ce que vous avez localement. git Push --force est fortement déconseillé car il peut détruire d'autres commits déjà envoyés à un référentiel partagé. L'une des causes les plus courantes des poussées de force est lorsque nous sommes obligés de rebaser une branche.

Par exemple. Nous avons un projet avec une branche technique sur laquelle Alice et Bob vont travailler. Ils ont tous deux cloné ce référentiel et commencé à travailler. Alice termine initialement sa partie de la fonctionnalité et la transfère au référentiel principal. Tout cela est bien et bon. Bob termine également son travail, mais avant de le pousser, il constate que certains changements ont été fusionnés dans master. Voulant garder un arbre vierge, il effectue un rebasement contre la branche principale. Bien sûr, quand il passera à Push, cette branche rebasée sera rejetée. Cependant, ne réalisant pas qu'Alice a déjà poussé son travail, il effectue un Push -force. Malheureusement, cela effacera tout l'enregistrement des modifications d'Alice dans le référentiel central.

Ce que - force-avec-bail refuse de mettre à jour une branche, sauf s'il s'agit de l'état attendu; c'est-à-dire que personne n'a mis à jour la branche en amont. En pratique, cela fonctionne en vérifiant que la référence en amont correspond à ce que nous attendons, car les références sont des hachages et codent implicitement la chaîne de parents dans leur valeur.

Here est un bon post concernant git Push --force et git Push --force-with-lease.

14
Shakil

Vous recherchez une réponse à partir de sources crédibles et/ou officielles.

Le "comparer et échanger" mentionné par torek dans les commentaires et dans son autre réponse est encore ignoré par les sources de Git lui-même .

ce dernier ne pousse que sur la télécommande si la télécommande n'a pas de commits que la branche locale n'a pas?

Cette fonctionnalité a été introduite dans commit 28f5d17 (décembre 2013, Git v1.8.5-rc0)

--force-with-lease protégera toutes les références distantes qui vont être mises à jour en exigeant que leur valeur actuelle soit identique à une valeur par défaut raisonnable, sauf indication contraire;

Pour le moment, "une valeur raisonnable par défaut" est provisoirement définie comme " la valeur de la branche de suivi à distance dont nous disposons pour le ref de la télécommande en cours de mise à jour " , et c’est une erreur si nous n’avons pas une telle branche de suivi à distance.

Donc, "bail" signifie:

"force-with-lease": Vous supposez que vous avez pris le bail de l'arbitre lorsque vous êtes allé chercher pour déterminer quel historique devrait être rebasé, et vous ne pouvez repousser que si le bail n'a pas été rompu.

Les sources mentionnent encore "cas":

  • Cette option s'appelait à l'origine "cas" (pour "comparer et échanger"), nom que personne n'a aimé parce qu'il était trop technique.
  • La deuxième tentative l'a appelé "lockref" (parce que c'est conceptuellement comme pousser après avoir verrouillé) mais le mot "verrou" a été détesté parce qu'il impliquait qu'il pouvait rejeter le Push par d'autres, ce qui n'est pas le cas de cette option.
  • Cette ronde l’appelle "force avec bail".
    Vous supposez que vous avez pris le bail sur l’arbitre lorsque vous êtes allé chercher pour décider de l’historique des rebasements, et vous ne pouvez repousser que si le bail n’a pas été rompu.

Donc: "git Push --force-with-lease vs. --force"

Comme je l'ai mentionné dans " Push --force-with-lease par défaut ", comme le mentionne Git 2.13 (T2 2017), l'option --force-with-lease peut être ignorée si un processus en arrière-plan (comme ceux que vous trouvez dans un IDE avec un plugin Git) exécute git fetch Origin.
Dans ce cas, --force l’emporte.

13
VonC

En supposant que les points d'ancrage de pré-réception sur le serveur acceptent le Push, cela réussira toujours:

git Push --force

Considérant que ceci lance une vérification spécifique côté client avant de procéder:

git Push --force-with-lease

Vous pouvez exécuter la vérification spécifique vous-même manuellement. Voici l'algorithme de "vérification de bail":

  1. Déterminez votre branche actuelle.

  2. Exécutez git for-each-ref refs/remotes. Prenez note du commit-id que votre client git pense correspondre à l’état en amont de votre branche actuelle.

Par exemple, si vous êtes sur la branche "foo", prenez note de l'ID de validation associé à "refs/remotes/Origin/foo".

  1. Déterminez le commit-id actuel de la branche distante sur le serveur git en amont pour le moment.

  2. Ne laissez le "git Push" continuer que si les ID de validation que vous avez extraits aux étapes 2 et 3 sont en accord. En d’autres termes, ne continuez que si la notion d’amont de votre clone git local est en accord avec l’amont actuel.

Cela implique une triste implication: puisque git fetch met à jour toutes les références sous "refs/remotes/Origin/*" avec leurs dernières versions, cette combinaison de commandes est essentiellement identique à git Push --force:

git fetch

# The command below behaves identically to "git Push --force"
# if a "git fetch" just happened!

git Push --force-with-lease

Pour contourner cette faiblesse inhérente dans git Push --force-with-lease, j'essaie de ne jamais exécuter git fetch. Au lieu de cela, je lance toujours git pull --rebase chaque fois que je dois effectuer une synchronisation en amont, car git pull ne met à jour qu'une seule référence sous refs/remote, en conservant le "bail" de --force-with-lease.

4
G. Sylvie Davies

La force avec bail n'est pas nécessairement sûre. Cela fonctionne comme dit Sylvie. Une remarque: dans git, une branche n’est qu’un pointeur sur un commit. Et commit pointe sur zéro ou plusieurs commits parent. Même si vous avez entièrement changé de branche avec une réinitialisation forcée et une poussée forcée ou poussée avec - - force avec bail sans le vouloir, ce n'est pas nécessairement un gros problème. Vous pouvez utiliser votre git reflog local pour voir comment votre astuce locale sur les branches (Où était HEAD à ce moment-là?) A été modifiée et réinitialisée, puis appuyez à nouveau sur la branche. Ensuite, vous ne perdez que les nouveaux commits sur la branche distante, mais même ceux-ci peuvent être restaurés par les membres de l'équipe.

1
Fish