228 votes

Git réinitialiser --hard et pousser vers le dépôt distant

J'avais un dépôt qui avait quelques mauvais commits (D, E et F pour cet exemple).

A-B-C-D-E-F master et origin/master

J'ai modifié le dépôt local spécifiquement avec un git reset --hard. J'ai pris une branche avant la réinitialisation donc maintenant j'ai un dépôt qui ressemble à :

A-B-C master  
     \ D-E-F old_master

A-B-C-D-E-F origin/master

Maintenant j'avais besoin de certaines parties de ces mauvais commits donc j'ai cherry-pické les morceaux dont j'avais besoin et j'ai fait quelques nouveaux commits donc maintenant j'ai ce qui suit localement :

A-B-C-G-H master
     \ D-E-F old_master

Maintenant je veux pousser cet état des choses vers le dépôt distant. Cependant, lorsque j'essaie de faire un git push, Git me rejette poliment :

$ git push origin +master:master --force  
Total 0 (delta 0), reused 0 (delta 0)  
error: denying non-fast forward refs/heads/master (you should pull first)  
To git@git.example.com:myrepo.git  
! [remote rejected] master -> master (non-fast forward)  
error: failed to push some refs to 'git@git.example.com:myrepo.git'  

Comment faire pour que le dépôt distant accepte l'état actuel du dépôt local ?

2 votes

Il s'agit d'un duplicate "presque" de plusieurs questions "comment puis-je pousser des questions d'historique amendées", par exemple, voir la réponse ici stackoverflow.com/questions/253055/…

2 votes

C'est vrai et j'avais cherché sur StackOverflow une réponse avant de poster. Cependant, ma recherche n'avait trouvé que des réponses dans lesquelles un git push --force résolvait le problème. Merci d'avoir partagé le lien vers votre publication :)

2 votes

Tu pourras bientôt (git1.8.5, Q4 2013) être en mesure de faire un git push -force de manière plus prudente.

308voto

Jakub Narębski Points 87537

Si forcer une poussée ne fonctionne pas (git push --force origin ou git push --force origin master devrait suffire), cela pourrait signifier que le serveur distant refuse les poussées non fast-forwards, via soit la variable de configuration receive.denyNonFastForwards (voir la page de manuel de git config pour la description), soit via un crochet de mise à jour/pré-réception.

Avec une ancienne version de Git, vous pouvez contourner cette restriction en supprimant git push origin :master (notez le : avant le nom de la branche) puis en recréant git push origin master donné la branche.

Si vous ne pouvez pas changer cela, alors la seule solution serait au lieu de réécrire l'historique pour créer un commit revertant les changements dans D-E-F:

A-B-C-D-E-F-[(D-E-F)^-1]   master

A-B-C-D-E-F                origin/master

3 votes

@JakubNarebski, merci. git revert HEAD~N a aidé. N est le nombre de validations. Par exemple, si j'ai besoin de la validation précédente, j'utiliserai git revert HEAD~1

1 votes

Et soyez conscient que vous allez perturber le travail des autres en modifiant ceci.

25voto

Jealie Points 1139

Pour compléter la réponse de Jakub, si vous avez accès au serveur git distant en ssh, vous pouvez vous rendre dans le répertoire distant git et définir :

user@remote$ git config receive.denyNonFastforwards false

Ensuite, retournez à votre dépôt local, essayez à nouveau de faire votre commit avec --force :

user@local$ git push origin +master:master --force

Et enfin, rétablissez le paramètre du serveur dans l'état protégé d'origine :

user@remote$ git config receive.denyNonFastforwards true

0 votes

Voir aussi pete.akeo.ie/2011/02/denying-non-fast-forward-and.html pour des informations spécifiques à sourceforge sur ce sujet.

0 votes

Des instructions détaillées sur la façon de désactiver denyNonFastForwards à l'aide de vi sont fournies sur cet article SO: stackoverflow.com/a/43721579/2073804

15voto

Jason Faulkner Points 5913

Pour les utilisateurs de GitHub, cela a fonctionné pour moi :

  1. Dans toutes les règles de protection de branche où vous souhaitez apporter le changement, assurez-vous que Laisser les poussées forcées est activé
  2. git reset --hard
  3. git push --force

Cela va "corriger" l'historique de la branche sur votre machine locale et sur le serveur GitHub, mais toute personne ayant synchronisé cette branche avec le serveur depuis mauvais commit aura l'historique sur sa machine locale. Si ils ont la permission de pousser directement sur la branche, alors ces commits réapparaîtront lorsqu'ils synchroniseront.

Tout ce que tout le monde d'autre doit faire est la commande git reset ci-dessus pour "corriger" la branche sur leur machine locale. Bien sûr, ils devraient prendre garde à tout commit local fait sur cette branche après le hash ciblé. Choisissez les commits nécessaires et réappliquez-les si besoin, mais si vous êtes dans une branche protégée alors le nombre de personnes pouvant pousser directement dessus est probablement limité.

3voto

Aidin Points 1068

Au lieu de réparer votre branche "master", il est beaucoup plus facile de l'échanger avec votre "desired-master" en renommant les branches. Voir https://stackoverflow.com/a/2862606/2321594. De cette façon, vous ne laisseriez même pas de trace des journaux de retour en arrière multiples.

1voto

Wolfgang Fahl Points 1920

Tout ce business de réinitialisation de git semblait bien trop compliqué pour moi.

Alors j'ai fait quelque chose dans ce style pour obtenir mon dossier src dans l'état dans lequel il était il y a quelques commits.

# réinitialiser l'état local
git reset  --hard 
# copier la partie pertinente par exemple src (l'exclusion n'est nécessaire que si vous spécifiez .)
tar cvfz /tmp/current.tgz --exclude .git  src
# obtenir l'état actuel de git
git pull
# supprimer ce que vous n'aimez plus
rm -rf src
# restaurer à partir du fichier tar
tar xvfz /tmp/current.tgz
# valider tout de nouveau dans git
git commit -a
# maintenant vous pouvez pousser correctement
git push

De cette façon, l'état des affaires dans le src est conservé dans un fichier tar et git est forcé d'accepter cet état sans trop de bidouillage, essentiellement le répertoire src est remplacé par l'état qu'il avait plusieurs commits plus tôt.

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