web-dev-qa-db-fra.com

Force "git Push" à écraser les fichiers distants

Je souhaite envoyer mes fichiers locaux et les placer dans un dépôt distant sans avoir à gérer de conflits de fusion. Je veux juste que ma version locale ait la priorité sur la version distante.

Comment puis-je faire cela avec Git?

666
opensas

Vous devriez pouvoir forcer votre révision locale sur le dépôt distant en utilisant

git Push -f <remote> <branch>

(par exemple, git Push -f Origin master). Si vous laissez <remote> et <branch> forcer Appuyez sur toutes les branches locales qui ont défini --set-upstream.

Sachez simplement que si d'autres personnes partagent ce référentiel, leur historique de révision sera en conflit avec le nouveau. Et s’ils ont des commits locaux après le changement, ils ne seront plus valables.

Update : Je pensais ajouter une note de côté. Si vous créez des modifications que d'autres personnes examineront, il n'est pas rare de créer une branche avec ces modifications et de rebasonner périodiquement pour les tenir à jour avec la branche de développement principale. Faites simplement savoir aux autres développeurs que cela se produira périodiquement pour 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 fait l'expérience. une force Push.

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

 D ---- E thème 
 /
A----B----C développement 

Mais plus tard, la branche development est touchée par un rebase, ce qui me fera recevoir une erreur comme lorsque je lance git pull:

 Déballer des objets: 100% (3/3), terminé. 
 Depuis <repo-location> 
 * Développement de branches -> FETCH_HEAD 
 Fusion automatique <fichiers > 
 CONFLICT (contenu): Conflit de fusion dans <emplacements> 
 La fusion automatique a échoué; corrige les conflits puis valide le résultat. 

Ici, je pourrais résoudre les conflits et commit, mais cela me laisserait avec une histoire de commit vraiment moche:

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

Il peut sembler intéressant d’utiliser git pull --force mais soyez prudent car cela vous laissera des commits échoués:

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

La meilleure option est donc probablement de faire un git pull --rebase. Cela me demandera de résoudre les conflits comme avant, mais pour chaque étape, au lieu de commettre, je vais utiliser git rebase --continue. En fin de compte, l’historique des commits sera bien mieux présenté:

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

Mise à jour 3: Vous pouvez également utiliser l'option --force-with-lease comme force "plus sûre". Push, comme mentionné par Cupcake dans son réponse :

Le fait de forcer avec un "bail" autorise l'échec de la force de poussée s'il y a de nouveaux commits inattendus sur la télécommande (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 que vous ne saviez même pas encore et vous voulez juste écraser les vôtres:

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

Vous pouvez en apprendre plus sur l'utilisation de --force-with-lease en lisant les informations suivantes:

952
Trevor Norris

Vous voulez forcer Push

Ce que vous voulez fondamentalement faire est de forcer Push votre branche locale, pour écraser celle distante.

Si vous souhaitez une explication plus détaillée de chacune des commandes suivantes, consultez ma section de détails ci-dessous. Vous avez essentiellement 4 options différentes pour pousser la 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 souhaitez une explication plus détaillée de chaque commande, reportez-vous à la section Réponses ci-dessous.

Avertissement: le forcer écrasera la branche distante par l'état de la branche que vous poussez. Assurez-vous que c'est bien ce que vous voulez vraiment faire avant de l'utiliser, sinon vous risquez d'écraser les commits que vous voulez réellement conserver.

Forcer les détails

Spécifier la télécommande et la branche

Vous pouvez complètement spécifier des branches spécifiques et une télécommande. Le drapeau -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 vers Push branche est omise, Git la déterminera en fonction de vos paramètres de configuration. Dans les versions de Git ultérieures à la version 2.0, un nouveau référentiel aura les 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 comportaient des paramètres par défaut permettant d'envoyer plusieurs branches locales. Les réglages en question sont les réglages remote.<remote>.Push et 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 git Push --force uniquement est déterminé par vos paramètres Push.default Git config:

git Push --force
  • À partir de Git 2.0, le paramètre par défaut, simple, consiste simplement à pousser votre branche actuelle vers son contre-partie distante en amont. La télécommande est déterminée par le paramètre branch.<remote>.remote de la branche et passe par défaut au référentiel d'origine.

  • Avant la version 2.0 de Git, le paramètre par défaut, matching, consiste simplement à déplacer toutes vos branches locales vers des branches portant le même nom sur la télécommande (la valeur par défaut étant Origine).

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

Forcer à pousser plus sûrement avec --force-with-lease

Le fait de forcer avec un "bail" autorise l'échec de la force de poussée s'il y a de nouveaux commits inattendus sur la télécommande (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 que vous ne saviez même pas encore et vous voulez juste écraser les vôtres:

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

Vous pouvez en apprendre plus sur l'utilisation de --force-with-lease en lisant les informations suivantes:

118
user456814

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

  • placez vos nouveaux commits dans une branche dédiée
  • réinitialiser votre master sur Origin/master
  • fusionner votre branche dédiée avec master, en gardant toujours les commits de la branche dédiée (ce qui signifie créer de nouvelles révisions sur master qui reflèteront votre branche dédiée).
    Voir " commande git pour créer une branche comme une autre) " pour connaître les stratégies permettant de simuler un git merge --strategy=theirs.

De cette façon, vous pouvez pousser maître à distance sans rien forcer.

29
VonC

git Push -f est un peu destructeur car il réinitialise toutes les modifications à distance apportées par quelqu'un d'autre de l'équipe. Une option plus sûre est {git Push --force-with-lease}.

{--Force-with-lease} refuse de mettre à jour une branche, sauf si c'est 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. 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. En pratique, cela signifie que, lorsque Alice mettra à jour sa branche et la transmettra au référentiel distant, la tête de référence de la branche sera mise à jour. Désormais, à moins que Bob ne tire la télécommande, sa référence locale à la télécommande sera périmée. Lorsqu'il utilise Push avec {--force-with-lease}, git vérifie la référence locale par rapport à la nouvelle télécommande et refuse de forcer la Push. {--force-with-lease} ne vous permet effectivement de forcer-Push que si personne d'autre n'a transmis les modifications à la télécommande dans l'intervalle. C'est {--force} avec la ceinture de sécurité.

3
Lando Ke

fonctionne pour moi git Push --set-upstream origin master

0
Jithish P N