Question Forcer "git push" pour é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 ait la priorité sur la version distante.

Comment puis-je faire cela avec Git?


543
2018-05-09 05:45


origine


Réponses:


Vous devriez pouvoir forcer votre révision locale vers le repo distant en utilisant

git push -f <remote> <branch>

(par exemple. git push -f origin master). Partir <remote> et <branch> va forcer pousser toutes les branches locales qui ont mis --set-upstream.

Juste être prévenu, 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 engagements locaux après le changement, ils deviendront invalides.

Mettre à jour: Je pensais que j'ajouterais une note de côté. Si vous créez des modifications que d'autres vont réviser, il n'est pas rare de créer une branche avec ces modifications et de les modifier régulièrement pour les maintenir à jour avec la branche de développement principale. Laissez les autres développeurs savoir que cela arrivera périodiquement pour qu'ils sachent à quoi s'attendre.

Mise à jour 2: En raison du nombre croissant de spectateurs, je voudrais ajouter quelques informations supplémentaires sur ce qu'il faut faire lorsque votre upstream connaît une poussée de force.

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

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

Mais plus tard, le development branche est frappé avec un rebase, ce qui me fera recevoir une erreur comme ça quand je cours git pull:

Déballage des objets: 100% (3/3), terminé.
De <repo-location>
 * développement de la succursale -> FETCH_HEAD
Fusion automatique <fichiers>
CONFLICT (contenu): Fusionner le conflit dans <emplacements>
La fusion automatique a échoué. résoudre les conflits et ensuite valider le résultat.

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

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

Il pourrait sembler alléchant d'utiliser git pull --force mais faites attention car cela vous laissera avec des commits bloqués:

            D ---- E sujet

A ---- B ---- C 'développement

Donc, la meilleure option est probablement de faire un git pull --rebase. Cela me demandera de résoudre tous les conflits comme avant, mais pour chaque étape au lieu de commettre je vais utiliser git rebase --continue. En fin de compte l'histoire de commit sera beaucoup mieux:

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

Mise à jour 3: Vous pouvez également utiliser le --force-with-lease option comme une force "plus sûre" pousser, comme mentionné par Cupcake dans son répondre:

Forcer la poussée avec un «bail» permet à la force d'échouer s'il y a   sont 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),   est utile si vous ne voulez pas écraser accidentellement quelqu'un d'autre   commet 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 apprendre plus de détails sur la façon d'utiliser --force-with-leasepar   lire l'un des éléments suivants:


781
2018-05-09 05:48



Vous voulez forcer la poussée

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

Si vous souhaitez une explication plus détaillée de chacune des commandes suivantes, consultez la section sur les 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 voulez une explication plus détaillée de chaque commande, alors voir ma section de longues réponses ci-dessous.

Attention: force push écrasera la branche distante avec l'état de la branche que vous pousserez. Assurez-vous que c'est ce que vous voulez vraiment faire avant de l'utiliser, sinon vous risquez d'écraser les commits que vous voulez conserver.

Force à pousser les détails

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

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

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

Omettre la branche

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

git push <remote> --force

Bien 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 remote.<remote>.push et push.default paramètres (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 est déterminé par votre push.default Paramètres de configuration Git:

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

  • Avant Git version 2.0, le paramètre par défaut, matching, fondamentalement pousse juste toutes vos branches locales aux branches avec le même nom sur la télécommande (qui par défaut à l'origine).

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

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

Forcer le push avec un "bail" permet à la force d'échouer s'il y a de nouveaux commit sur la télécommande auxquels vous ne vous attendiez pas (techniquement, si vous ne les avez pas encore récupérés dans votre remote-tracking), 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 apprendre plus de détails sur la façon d'utiliser --force-with-lease en lisant l'un des documents suivants:


100
2017-07-15 21:21



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

  • mettez vos nouveaux commits dans une branche dédiée
  • réinitialiser votre master sur origin/master
  • fusionner votre branche dédiée à master, en gardant toujours les engagements de la branche dédiée (ce qui signifie créer de nouvelles révisions au-dessus de master qui reflétera votre branche dédiée).
    Voir "commande git pour faire une branche comme une autre"pour des stratégies pour simuler git merge --strategy=theirs.

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


25
2018-05-09 06:00



git push -f est un peu destructeur car il réinitialise tous les changements à distance qui ont été effectués par quelqu'un d'autre dans 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 sauf si c'est 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 le ref amont est ce que nous attendons, parce que refs sont des hashes, et encodent implicitement la chaîne de parents dans leur valeur. Vous pouvez dire à {--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 dans la pratique est que lorsqu'Alice met à jour sa branche et la pousse vers le référentiel distant, la tête de pointage de la branche sera mise à jour. Maintenant, à moins que Bob ne tire sur la télécommande, sa référence locale à la télécommande sera périmée. Quand il va pousser en utilisant {--force-with-lease}, git va vérifier la référence locale par rapport à la nouvelle télécommande et refuse de forcer le push. {--force-with-lease} vous permet seulement de forcer si personne d'autre n'a poussé les changements jusqu'à la télécommande dans l'intervalle. C'est {--force} avec la ceinture de sécurité.


2
2017-07-05 11:32