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 ma version locale ont priorité sur la télécommande.

Comment faire avec Git?

563
demandé sur opensas 2012-05-09 09:45:38

4 réponses

vous devriez pouvoir forcer votre révision locale à la prise en compte à distance en utilisant

git push -f <remote> <branch>

(par exemple git push -f origin master ). Le fait de laisser <remote> et <branch> forcera toutes les branches locales qui ont mis --set-upstream .

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

Update : J'ai pensé que je voudrais ajouter un side-note. Si vous créez des changements que d'autres examineront, il n'est pas rare de créer une branche avec ces changements et de les reformuler périodiquement pour les tenir à jour avec la branche principale du développement. Il suffit de faire savoir aux 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 lorsque votre upstream subit une poussée de force.

dites 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 la branche development est frappée avec un rebase , ce qui me fera recevoir une erreur comme ça quand je cours 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 que me laisserait avec une histoire de commit vraiment laid:

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

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

            D----E   topic

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

donc probablement la meilleure option est de faire un git pull --rebase . Cela me demandera de résoudre tous les conflits comme avant, mais pour chaque pas au lieu de commettre je vais utiliser git rebase --continue . À la fin l'histoire de commit paraîtra beaucoup mieux:

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

mise à jour 3: vous pouvez également utiliser l'option --force-with-lease comme une force "plus sûre" push, comme mentionné par Cupcake dans son réponse :

Force de poussée avec un "contrat de location" permet à la force de pousser à l'échec si il y sont de nouvelles propagations sur la télécommande que vous ne vous attendiez pas (techniquement, si vous ne les avez pas encore amenés dans votre branche de suivi à distance), ce qui est utile si vous ne voulez pas écraser accidentellement quelqu'un d'autre engage que vous ne saviez même pas encore, et vous voulez juste remplacer le vôtre:

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

Vous pouvez apprendre plus de détails sur la façon d'utiliser --force-with-lease par

805
répondu Trevor Norris 2017-05-23 12:26:21

Vous voulez de la force de poussée

ce que vous voulez essentiellement faire est de forcer votre branche locale, afin d'écraser la plus éloignée.

si vous voulez une explication plus détaillée de chacune des commandes suivantes, alors voyez ma section détails ci-dessous. Vous avez essentiellement 4 options différentes pour la poussée de force 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 voulez une explication plus détaillée de chaque commande, puis voir ma longue la section Réponses ci-dessous.

Avertissement: force qui va remplacer la télécommande de la direction, avec l'état de la branche que vous poussez. Assurez-vous que c'est vraiment ce que vous voulez faire avant de l'utiliser, sinon vous risquez d'écraser engage que vous voulez garder.

détails de poussée de force

spécifiant la télécommande et la branche

vous pouvez spécifier complètement branches spécifiques et une télécommande. Le drapeau -f est la version courte de --force

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

l'Omission de la branche

lorsque la branche à push branch est omise, Git la trouvera en fonction de vos paramètres de configuration. Dans les versions Git après 2.0, un nouveau repo aura les paramètres par défaut pour pousser la branche actuellement cochée:

git push <remote> --force

alors qu'avant 2.0, les nouvelles pensions auront des paramètres par défaut pour pousser de multiples branches locales. Les paramètres en question sont les paramètres remote.<remote>.push et push.default (voir ci-dessous).

l'Omission de la distance et de la direction générale

lorsque la télécommande et la branche sont omises, le comportement de juste git push --force est déterminé par vos paramètres de configuration push.default Git:

git push --force
  • à partir de Git 2.0, le réglage par défaut, simple , va simplement pousser votre branche actuelle à sa contre-partie distante amont. La distance est déterminée par le paramètre branch.<remote>.remote de la branche, et par défaut par rapport à l'origine repo.

  • avant Git version 2.0, le paramètre par défaut, matching , ne fait que pousser toutes vos branches locales vers les branches avec le même nom sur la télécommande (qui par défaut à l'origine).

vous pouvez lire la suite "" paramétrage en lisant git help config ou une version en ligne de la Page de manuel git-config(1) .

Force de poussée de façon plus sécuritaire avec --force-with-lease

Force de poussée avec un "contrat de location" permet à la force de pousser à l'échec si il y a des nouveaux commits sur la distance que vous ne vous attendiez pas (techniquement, si vous n'avez pas récupéré votre compte à distance-le suivi de la succursale encore), ce qui est utile si vous ne voulez pas écraser accidentellement quelqu'un d'autre engage que vous ne saviez même pas encore, et vous voulez juste écraser votre propre:

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

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

102
répondu Community 2017-05-23 12:10:31

une autre option (pour éviter toute poussée forcée qui peut être problématique pour d'autres contributeurs) est de:

  • mettez vos nouvelles commits dans une branche dédiée
  • Réinitialisez votre master sur origin/master
  • fusionnez votre branche dédiée à master , en gardant toujours les propagations de la branche dédiée (ce qui signifie créer de nouvelles révisions en haut de master qui reflétera votre branche dédiée).

    Voir " commande git pour la fabrication de branche en branche comme un autre " pour les 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.

25
répondu VonC 2018-01-16 06:59:06

git push-f est un peu destructeur parce qu'il réinitialise tous les changements à distance qui ont été faits par quelqu'un d'autre dans l'équipe. Une option plus sûre est {git push --force-avec-bail}.

ce que fait {--force-with-lease} est de refuser de mettre à jour une branche à moins que ce ne soit l'état que nous attendons; c.-à-d. que personne n'a mis à jour la branche en amont. En pratique cela fonctionne en vérifiant que le ref amont est ce que nous attendons, parce que les ref sont des hashs, et encodent implicitement la chaîne des parents dans leur valeur. Vous pouvez dire à {--force-with-lease} exactement ce qu'il faut vérifier, mais par défaut vérifiera l'ref distante actuelle. Ce que cela signifie en pratique, c'est que lorsque Alice met à jour sa branche et la pousse vers le dépôt distant, la tête de pointage ref de la branche sera mise à jour. Maintenant, à moins que Bob ne tire de la télécommande, sa référence locale à la télécommande sera périmée. Quand il va à push en utilisant {--force-with-lease}, git vérifiera l'réf locale contre la nouvelle télécommande et refusez de forcer la poussée. {--force-with-lease} ne permet de forcer que si personne d'autre n'a poussé les changements à la télécommande dans l'intervalle. C'est {--force} avec la ceinture de sécurité.

2
répondu Lando Ke 2017-07-05 11:32:34