Forcer «git push» à écraser les fichiers distants

769

Je veux pousser mes fichiers locaux et les avoir sur un référentiel 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?

opensas
la source
106
Vous n'avez git push origin --forcepas travaillé pour vous?
Il n'est pas clair si vous souhaitez uniquement 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 souhaitez mettre à jour la copie de travail distante, vous devez utiliser un hook post-réception
Pierre-Olivier Vares
@Mike qui fonctionne pour moi pour une raison quelconque ... me demande ce qui s'est
Une cause probable, la poussée forcée ne fonctionne pas, est qu'elle a peut-être été explicitement désactivée sur le référentiel distant (pour garantir que rien ne soit perdu en raison de contributeurs idiots et / ou malveillants): utilisez config receive.denyNonFastforwardspour le savoir.
Frank Nocke

Réponses:

1089

Vous devriez être en mesure de forcer votre révision locale sur le référentiel distant en utilisant

git push -f <remote> <branch>

(par exemple git push -f origin master). Quitter <remote>et <branch>forcera à pousser toutes les branches locales qui se sont établies --set-upstream.

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

Mise à jour : J'ai pensé que j'ajouterais une note secondaire. Si vous créez des modifications que d'autres examineront, il n'est pas rare de créer une branche avec ces modifications et de rebaser périodiquement pour les maintenir à jour avec la branche de développement principale. Faites simplement 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 des informations supplémentaires sur ce qu'il faut faire lorsque votre upstreamforce subit une poussée forcée.

Disons que j'ai cloné votre dépôt et que j'ai ajouté quelques commits comme ceci:

            Sujet D ---- E
           /
Développement A ---- B ---- C

Mais plus tard, la developmentbranche est frappée d'un rebase, ce qui me fera recevoir une erreur comme celle-ci lorsque j'exécuterai git pull:

Déballage des objets: 100% (3/3), c'est fait.
De <repo-location>
 * développement de succursales -> FETCH_HEAD
Fusion automatique des <fichiers>
CONFLICT (contenu): fusionner le conflit dans <locations>
La fusion automatique a échoué; résoudre les conflits, puis valider le résultat.

Ici, je pouvais résoudre les conflits et commit, mais cela me laisserait un historique de commit vraiment moche:

       C ---- D ---- E ---- F sujet
      / /
A ---- B -------------- C 'développement

Cela peut sembler attrayant à utiliser, git pull --forcemais soyez prudent car cela vous laissera des commits bloqués:

            Sujet D ---- E

Développement A ---- B ---- C '

Donc, la meilleure option est probablement de faire un git pull --rebase. Cela me demandera de résoudre tout conflit comme avant, mais pour chaque étape, au lieu de valider, je l'utilise git rebase --continue. Au final, l'historique des validations sera bien meilleur:

            Sujet D '--- E'
           /
Développement A ---- B ---- C '

Mise à jour 3: Vous pouvez également utiliser l' --force-with-leaseoption comme une poussée de force "plus sûre", comme mentionné par Cupcake dans sa réponse :

La poussée forcée avec un "bail" permet l'échec de la poussée forcée s'il y a de nouveaux commits sur la télécommande que vous ne vous attendiez pas (techniquement, si vous ne les avez pas encore récupérés dans votre branche de suivi à distance), ce qui est utile si vous ne voulez pas écraser accidentellement les commits de quelqu'un d'autre que vous ne connaissiez même pas encore, et vous voulez juste écraser les vôtres:

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

Vous pouvez en savoir plus sur la façon d'utiliser --force-with-leaseen lisant l'un des éléments suivants:

Trevor Norris
la source
5
Puisque c'est la réponse choisie, je commenterai ici. Utiliser la force n'est pas un problème lorsque vous travaillez seul. Par exemple, mon hôte cloud commence par son propre git. Si je travaille localement et que je crée un projet et que je souhaite le mettre sur mon hôte cloud (OpenShift), j'ai deux projets git distincts. Mon local et mon OpenShift. Je reçois mon local comme je le souhaite, mais je souhaite maintenant le prévisualiser sur mon OpenShift. Vous poussez ensuite vers OpenShift pour la première fois, en utilisant l' -findicateur. Mettre essentiellement votre git local sur OpenShift.
Wade
128

Vous voulez forcer la poussée

Ce que vous voulez essentiellement faire est de forcer le push de votre branche locale, afin d'écraser la distante.

Si vous souhaitez une explication plus détaillée de chacune des commandes suivantes, consultez la section Mes détails ci-dessous. Vous avez essentiellement 4 options différentes pour forcer la poussée 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, alors voyez mes longues réponses ci-dessous.

Avertissement: une poussée forcée écrasera la branche distante avec l'état de la branche que vous poussez. Assurez-vous que c'est ce que vous voulez vraiment faire avant de l'utiliser, sinon vous risquez d'écraser les commits que vous souhaitez réellement conserver.

Force poussant les détails

Spécification de la télécommande et de la branche

Vous pouvez spécifier complètement des branches spécifiques et une télécommande. Le -fdrapeau est la version courte de--force

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

Omettre la succursale

Lorsque la branche à pousser est omise, Git le trouvera en fonction de vos paramètres de configuration. Dans les versions Git après 2.0, un nouveau dépôt aura des paramètres par défaut pour pousser la branche actuellement extraite:

git push <remote> --force

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

Omettre la télécommande et la branche

Lorsque la télécommande et la branche sont omises, le comportement de just git push --forceest déterminé par vos push.defaultparamètres de configuration Git:

git push --force
  • À partir de Git 2.0, le paramètre par défaut simple,, poussera simplement votre branche actuelle vers sa contrepartie distante en amont. La télécommande est déterminée par le branch.<remote>.remoteréglage de la branche , et revient par défaut au dépôt d'origine sinon.

  • Avant Git version 2.0, le paramètre par défaut matching,, pousse simplement toutes vos branches locales vers des branches portant le même nom sur la télécommande (qui par défaut est d'origine).

Vous pouvez lire plus de push.defaultparamètres en lisant git help configou une version en ligne de la page de manuel git-config (1) .

Forcez à pousser plus en toute sécurité avec --force-with-lease

La poussée forcée avec un "bail" permet l'échec de la poussée forcée s'il y a de nouveaux commits sur la télécommande que vous ne vous attendiez pas (techniquement, si vous ne les avez pas encore récupérés dans votre branche de suivi à distance), ce qui est utile si vous ne voulez pas écraser accidentellement les commits de quelqu'un d'autre que vous ne connaissiez même pas encore, et vous voulez juste écraser les vôtres:

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

Vous pouvez en savoir plus sur la façon d'utiliser --force-with-leaseen lisant l'un des éléments suivants:

Communauté
la source
Vous avez raison, mais cela ne devrait vraiment être utilisé que dans des situations exceptionnelles .
Scott Berrevoets
1
@ScottBerrevoets " Je préférerais pousser ce que j'ai et le laisser écraser à distance plutôt qu'intégrer. " J'ai donné au PO exactement ce qu'il avait demandé.
Je sais, mais OP peut ne pas être conscient des conséquences de faire cela. Vous avez techniquement répondu à la question, mais je pense qu'un avertissement de ne pas le faire n'est pas hors de propos.
Scott Berrevoets
1
@ScottBerrevoets J'essaie d'avoir un modérateur fusionner ma réponse dans le canonique, parce que je mentionne la nouvelle --force-with-leaseoption;)
1
FYI: fusionné de stackoverflow.com/questions/24768330/…
Shog9
32

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

  • mettez vos nouveaux commits dans une branche dédiée
  • réinitialiser votre mastersurorigin/master
  • fusionnez votre branche dédiée à master, en gardant toujours les validations de la branche dédiée (ce qui signifie créer de nouvelles révisions au-dessus masterdesquelles reflétera votre branche dédiée).
    Voir " Commande git pour créer une branche comme une autre " pour les stratégies de simulation a git merge --strategy=theirs.

De cette façon, vous pouvez pousser master à distance sans avoir à forcer quoi que ce soit.

VonC
la source
En quoi le résultat diffère-t-il de "push -force"?
alexkovelsky
6
@alexkovelsky Toute poussée forcée réécrirait l'historique, forçant les autres utilisateurs du référentiel à réinitialiser leur propre référentiel local pour correspondre aux commits nouvellement poussés. Cette approche ne crée que de nouveaux commits et ne nécessite pas de poussée forcée.
VonC
1
Je vous suggère d'ajouter un titre à votre réponse: "Vous ne voulez pas forcer la poussée" :)
alexkovelsky
@alexkovelsky Bon point. J'ai modifié la réponse en conséquence.
VonC
4

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

Ce que {--force-with-lease} fait est de refuser de mettre à jour une branche à moins que ce soit 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 amont est ce que nous attendons, car les références sont des hachages et codent implicitement la chaîne de parents en leur valeur. Vous pouvez dire à {--force-with-lease} exactement ce qu'il faut vérifier, mais par défaut vérifiera la référence distante actuelle. En pratique, cela signifie que lorsque Alice met à jour sa branche et la pousse vers le référentiel distant, la tête de pointage de référence de la branche est mise à jour. Maintenant, à moins que Bob ne tire de la télécommande, sa référence locale à la télécommande sera obsolète. Quand il va pousser en utilisant {--force-with-lease}, git vérifiera la référence locale par rapport à la nouvelle télécommande et refusera de forcer la poussée. {--force-with-lease} ne vous permet de forcer le push que si personne d'autre n'a poussé les modifications vers la télécommande entre-temps. C'est {--force} avec la ceinture de sécurité.

Lando Ke
la source
3

Travaille pour moi:

git push --set-upstream origin master -f
Jithish PN
la source
0

Étapes simples en utilisant tortoisegit

GIT en validant les fichiers locaux et en les poussant dans le référentiel git.

Pas :

1) la cachette change le nom de la cachette

2) tirer

3) cachette pop

4) Validez 1 ou plusieurs fichiers et donnez la description des modifications de validation à l'auteur et à la date

5) pousser

Nagnath Mungade
la source