1053 votes

Forcer "git push" à écraser les fichiers distants

Je veux pousser mes fichiers locaux, et les avoir sur un repo distant, sans avoir à gérer les conflits de fusion. Je veux juste que ma version locale soit prioritaire sur la version distante.

Comment puis-je faire cela avec Git ?

171 votes

Est-ce que git push origin --force ne fonctionne pas pour vous ?

3 votes

0 votes

Il n'est pas clair si vous voulez seulement remplacer les fichiers .git, ou la copie de travail associée. Si c'est le dépôt git, git push est la réponse. Si vous voulez mettre à jour la copie de travail distante, vous devez utiliser un hook post-receive.

1406voto

Trev Norris Points 2686

Vous devriez être en mesure de forcer votre révision locale vers le dépôt distant en utilisant

git push -f <remote> <branch>

(par exemple git push -f origin master ). Abandon <remote> et <branch> poussera de force toutes les branches locales qui ont défini --set-upstream .

Attention, si d'autres personnes partagent ce dépôt, leur historique de révision entrera en conflit avec le nouveau dépôt. Et s'ils ont des commits locaux après le point de changement, ils deviendront invalides.

Mise à jour : J'ai pensé ajouter une note complémentaire. Si vous créez des modifications qui seront revues par d'autres, il n'est pas rare de créer une branche avec ces modifications et de la rebaser périodiquement pour la maintenir à jour avec la branche de développement principale. Informez simplement les autres développeurs que cela se produira périodiquement afin qu'ils sachent à quoi s'attendre.

Mise à jour 2 : En raison du nombre croissant de téléspectateurs, j'aimerais ajouter quelques informations supplémentaires sur ce qu'il faut faire quand votre upstream subit une poussée de force.

Disons que j'ai cloné votre repo et que j'ai ajouté quelques commits comme ceci :

            D----E  topic
           /
A----B----C         development

Mais plus tard, le development La branche est frappée par un rebase ce qui m'amènera à recevoir une erreur comme celle-ci lorsque je lancerai le programme git pull :

Unpacking objects: 100% (3/3), done.
From <repo-location>
 \* branch            development     -> FETCH\_HEAD
Auto-merging <files>
CONFLICT (content): Merge conflict in <locations>
Automatic merge failed; fix conflicts and then commit the result.

Ici, je pourrais régler les conflits et commit mais cela me laisserait avec un historique de livraison vraiment moche :

       C----D----E----F    topic
      /              /
A----B--------------C'  development

Cela peut sembler séduisant d'utiliser git pull --force mais faites attention car cela vous laissera avec des commits bloqués :

            D----E   topic

A----B----C'         development

Donc probablement la meilleure option est de faire un git pull --rebase . Cela m'obligera à résoudre tous les conflits comme précédemment, mais pour chaque étape, au lieu de valider, j'utiliserai la méthode suivante git rebase --continue . Au final, l'historique des livraisons sera bien meilleur :

            D'---E'  topic
           /
A----B----C'         development

8 votes

Puisque c'est la réponse choisie, je vais commenter ici. L'utilisation de la force n'est pas un problème lorsque l'on travaille seul. Par exemple, mon hôte en nuage démarre avec son propre git. Si je travaille localement et que je construis un projet, et que je veux le mettre sur mon hôte cloud (OpenShift), j'ai deux projets git séparés. Mon projet local et mon projet OpenShift. J'obtiens mon local comme je l'entends, mais je veux maintenant le prévisualiser sur mon OpenShift. Vous poussez alors sur OpenShift pour la première fois, en utilisant -f drapeau. Essentiellement en mettant votre git local sur OpenShift.

1 votes

Vous pouvez également faire git push -f tant que la branche distante vers laquelle vous voulez pousser est la plus récente.

0 votes

"will force push all local branches" - Pourquoi pousserait-il autre chose que la branche active ?

159voto

Cupcake Points 22154

Vous voulez pousser de force

Ce que vous voulez faire, c'est de pousser votre branche locale, afin d'écraser la branche distante.

Si vous souhaitez une explication plus détaillée de chacune des commandes suivantes, consultez ma section détaillée ci-dessous. En fait, vous avez 4 options différentes pour forcer la mise à jour avec Git :

git push <remote> <branch> -f
git push origin master -f # Example

git push <remote> -f
git push origin -f # Example

git push -f

git push <remote> <branch> --force-with-lease

Si vous souhaitez une explication plus détaillée de chaque commande, consultez la section des réponses longues ci-dessous.

Attention : Force pushing va écraser la branche distante avec l'état de la branche que vous êtes en train de pousser. Assurez-vous que c'est bien ce que vous voulez faire avant de l'utiliser, sinon vous risquez d'écraser des commits que vous souhaitez conserver.

Détails de la poussée des forces

Spécifier la distance et la branche

Vous pouvez spécifier complètement des branches spécifiques et une télécommande. Le site -f est la version abrégée de --force

git push <remote> <branch> --force
git push <remote> <branch> -f

Omettre la branche

Lorsque la branche à pousser est omise, Git la détermine en fonction de vos paramètres de configuration. Dans les versions de Git postérieures à 2.0, un nouveau repo aura des paramètres par défaut pour pousser la branche actuellement extraite :

git push <remote> --force

alors qu'avant la version 2.0, les nouveaux dépôts auront des paramètres par défaut pour pousser plusieurs branches locales. Les paramètres en question sont les suivants remote.<remote>.push et push.default (voir ci-dessous).

Omettre le distant et la branche

Lorsque le distant et la branche sont omis, le comportement de seulement git push --force est déterminé par votre push.default Paramètres de configuration de Git :

git push --force
  • A partir de Git 2.0, le paramètre par défaut, simple En fait, il suffit de pousser votre branche actuelle vers sa contrepartie distante en amont. Le distant est déterminé par le paramètre branch.<remote>.remote et, par défaut, le repo d'origine.

  • Avant la version 2.0 de Git, le paramètre par défaut, matching En gros, il s'agit de pousser toutes vos branches locales vers les branches portant le même nom sur le serveur distant (qui est par défaut origin).

Vous pouvez lire la suite push.default les paramètres en lisant git help config ou une version en ligne de la page de manuel git-config(1) .

Pousser plus sûrement avec --force-with-lease

Le forçage avec un "bail" permet au forçage d'échouer s'il y a de nouveaux commits sur la branche distante que vous n'attendiez pas (techniquement, si vous ne les avez pas encore récupérés dans votre branche de suivi distante), ce qui est utile si vous ne voulez pas accidentellement écraser les commits de quelqu'un d'autre que vous ne connaissez même pas encore, et que vous voulez juste écraser les vôtres :

git push <remote> <branch> --force-with-lease

Vous pouvez obtenir plus de détails sur la façon d'utiliser --force-with-lease en lisant l'un des documents suivants :

2 votes

Vous avez raison, mais cela ne devrait être utilisé que dans les cas suivants exceptionnel situations.

1 votes

@ScottBerrevoets " Je préfère pousser ce que j'ai et le laisser écraser à distance plutôt que d'intégrer. " J'ai donné au PO exactement ce qu'il a demandé.

2 votes

Je sais, mais le PO n'est peut-être pas conscient des conséquences de cette action. Vous avez techniquement répondu à la question, mais je pense qu'un avertissement pour ne pas faire ça n'est pas déplacé.

36voto

VonC Points 414372

Une autre option est de :

  • mettez vos nouveaux commits dans une branche dédiée
  • réinitialiser votre master sur origin/master
  • fusionner votre branche dédiée vers master en conservant toujours les commits de la branche dédiée (c'est-à-dire en créant de nouvelles révisions au-dessus de la branche dédiée). master qui sera le miroir de votre branche dédiée).
    Voir " Commande git pour rendre une branche comme une autre " pour des stratégies visant à simuler un git merge --strategy=theirs .

De cette façon, vous pouvez pousser le maître à distance sans avoir à forcer quoi que ce soit.

0 votes

En quoi le résultat diffère-t-il de "push -force" ?

9 votes

@alexkovelsky Tout push forcé réécrirait l'historique, forçant les autres utilisateurs du repo à réinitialiser leur propre repo local pour correspondre aux commits nouvellement poussés. Cette approche ne crée que de nouveaux commits et ne nécessite pas de push forcé.

1 votes

Je vous suggère d'ajouter un titre à votre réponse : "Vous ne voulez pas forcer le passage" :)

22voto

Jithish P N Points 416

Ça marche pour moi :

git push --set-upstream origin master -f

13voto

Lando Ke Points 51

Git push -f est un peu destructeur car il réinitialise toutes les modifications à distance qui avaient été faites par n'importe quel autre membre de l'équipe. Une option plus sûre est {git push --force-with-lease}.

Ce que fait {--force-with-lease} est de refuser de mettre à jour une branche à moins qu'elle ne soit dans l'état que nous attendons ; 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 est ce que nous attendons, parce que les références sont des hachages, et encodent implicitement la chaîne des parents dans leur valeur. Vous pouvez indiquer à {--force-with-lease} exactement ce qu'il faut vérifier, mais par défaut, il vérifiera la référence distante actuelle. Ce que cela signifie en pratique, c'est que lorsque Alice met à jour sa branche et la pousse vers le référentiel distant, la tête de référence de la branche sera mise à jour. Maintenant, à moins que Bob ne fasse un pull depuis le dépôt distant, sa référence locale vers le dépôt distant ne sera pas à jour. Lorsqu'il va pousser en utilisant {--force-with-lease}, git va vérifier la référence locale par rapport au nouveau dépôt distant et refuser de forcer la poussée. {--force-with-lease} ne vous permet effectivement de forcer le push que si personne d'autre n'a poussé de changements vers le distant dans l'intervalle. C'est {--force} avec la ceinture de sécurité.

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