Comment puis-je pousser la commande Modified commit vers le dépôt Git distant?

quand j'ai travaillé un peu avec mon code source, j'ai fait mon truc habituel commit puis j'ai poussé vers un dépôt distant. Mais j'ai remarqué que j'avais oublié d'organiser mes importations dans le code source. Je fais donc la commande Modifier pour remplacer la précédente commit:

> git commit --amend

malheureusement, la propagation ne peut pas être repoussée vers le dépôt. Il est rejeté comme ceci:

> git push origin
To //my.remote.repo.com/stuff.git/
 ! [rejected]        master -> master (non-fast forward)
error: failed to push some refs to '//my.remote.repo.com/stuff.git/'

Que dois-je faire? (Je peux accéder au dépôt distant.)

539
demandé sur Peter Mortensen 2008-10-31 13:23:14

13 réponses

j'ai en fait poussé une fois avec --force et .git dépôt et a été grondé par Linus grand temps . En général, cela va créer beaucoup de problèmes pour d'autres personnes. Une réponse simple est "ne le faites pas".

je vois que d'autres ont donné la recette pour le faire de toute façon, donc je ne vais pas les répéter ici. Mais voici une astuce pour récupérer de la situation après vous avez expulsé la propagation modifiée avec --force (ou +maître.)

  1. trouvez l'ancienne commit que vous avez modifiée (appelez-la old , et nous appellerons la nouvelle commit que vous avez créée en modifiant new ).
  2. crée une fusion entre old et new , enregistrant l'arbre de new , comme git checkout new && git merge -s ours old .
  3. fusionnez cela à votre maître avec git merge master
  4. mettez à jour votre master avec le résultat git push . HEAD:master
  5. repoussez le résultat.

alors les gens qui ont eu la malchance d'avoir basé leur travail sur le commit que vous avez effacé en modifiant et en forçant une poussée (qui est vous êtes un très mauvais garçon ) verront la fusion résultant verra que vous favorisez new plutôt que old . Leurs fusions ultérieures ne verront pas les conflits entre old et new qui ont résulté de votre modification, ont à souffrir.

421
répondu 4444 2016-06-09 20:16:36

vous voyez un dispositif de sécurité Git. Git refuse de mettre à jour la branche distante avec votre branche, parce que la HEAD commit de votre branche n'est pas un descendant direct de la head commit actuelle de la branche vers laquelle vous poussez.

si ce n'était pas le cas, alors deux personnes poussant vers le même dépôt à peu près au même moment ne sauraient pas qu'il y a un nouveau commit qui arrive en même temps et que celui qui pousse en dernier perdrait le travail du précédent poussoir sans que l'une d'entre eux cette réalisation.

si vous savez que vous êtes la seule personne poussant et que vous voulez pousser une propagation modifiée ou pousser une propagation qui remonte la branche, vous pouvez 'forcer' Git à mettre à jour la branche distante en utilisant le commutateur -f .

git push -f origin master

même cela peut ne pas fonctionner car Git permet aux dépôts à distance de refuser les poussées Non rapides à l'extrémité en utilisant la variable de configuration receive.denynonfastforwards . Si ce est - ce que le motif de rejet ressemblera à ceci (notez la partie 'rejeté à distance'):

 ! [remote rejected] master -> master (non-fast forward)

pour contourner cela, vous devez soit modifier la configuration du dépôt distant ou comme un piratage sale vous pouvez supprimer et recréer la branche ainsi:

git push origin :master
git push origin master

en général le dernier paramètre de git push utilise le format <local_ref>:<remote_ref> , où local_ref est le nom de la branche sur le dépôt local et remote_ref est le nom de la branche sur le dépôt distant. Cette paire de commandes utilise deux raccourcis. :master a un null local_ref qui signifie pousser une branche nulle du côté distant master , c'est-à-dire supprimer la branche distante. Un nom de branche sans : signifie pousser la branche locale avec le prénom à la branche distante avec le même nom. master dans cette situation est l'abréviation de master:master .

241
répondu CB Bailey 2017-10-08 10:24:21

Quick rant: le fait que personne n'ait posté la réponse simple ici démontre l'hostilité désespérée de l'utilisateur manifestée par le Git CLI.

de toute façon, la façon" évidente " de faire cela, en supposant que vous n'avez pas essayé de forcer la poussée, est de tirer en premier. Cela tire le changement que vous avez modifié (et ainsi n'avez plus) afin que vous l'ayez à nouveau.

une fois que vous avez résolu les conflits, vous pouvez pousser à nouveau.

:

git pull

si vous avez des erreurs dans pull, peut-être que quelque chose ne va pas dans la configuration de votre dépôt local (j'ai eu un mauvais ref dans le .git/config direction de la section).

et après

git push

peut-être que vous obtiendrez un commit supplémentaire avec le sujet parlant d'une"fusion triviale".

194
répondu GabrieleV 2017-10-08 10:27:16

réponse Courte: Ne poussez pas modifié s'engage à un public de pensions.

longue réponse: Quelques commandes Git, comme git commit --amend et git rebase , réécrivent en fait le graphe historique. C'est très bien tant que vous n'avez pas publié vos changements, mais une fois que vous le faites, vous ne devriez vraiment pas vous mêler de l'histoire, parce que si quelqu'un a déjà eu vos changements, alors quand ils essaient de tirer à nouveau, il pourrait échouer. Au lieu de modifier un commit, vous devriez juste faire un nouveau commit avec les changements.

cependant, si vous voulez vraiment, vraiment pousser un commit modifié, vous pouvez le faire comme ceci:

$ git push origin +master:master

le premier signe + va forcer la poussée à se produire, même si cela ne se traduit pas par un "fast-forward" commit. (Une commit fast-forward se produit lorsque les changements que vous poussez sont un descendant direct des changements déjà dans le public repo.)

93
répondu mipadi 2008-10-31 14:35:12

voici un moyen très simple et propre pour pousser vos modifications après que vous avez déjà fait un commit --amend :

git reset --soft HEAD^
git stash
git push -f origin master
git stash pop
git commit -a
git push origin master

qui fait ce qui suit:

  • réinitialiser la tête de la branche à la propagation parent.
  • Planque ce dernier engagement.
  • force poussée à distance. La télécommande n'a pas le dernier engagement.
  • ouvrez votre planque.
  • Commit proprement.
  • à distance.

N'oubliez pas de changer" origine "et" maître " si vous l'appliquez à une branche différente ou à distance.

37
répondu Faiza 2017-11-15 21:12:56

Je l'ai résolu en rejetant mon commit modifié local et en ajoutant les nouveaux changements en haut:

# Rewind to commit before conflicting
git reset --soft HEAD~1

# Pull the remote version
git pull

# Add the new commit on top
git add ...
git commit
git push
21
répondu bara 2017-10-08 10:28:02

j'ai eu le même problème.

  • modifié accidentellement le dernier commit qui a déjà été poussé
  • fait beaucoup de changements localement, commis environ cinq fois
  • a essayé de pousser, a eu une erreur, a paniqué, a fusionné la télécommande, a eu beaucoup de non-my-files, a poussé, a échoué, etc.

en tant que débutant, je pensais que c'était complet FUBAR .

Solution: un peu comme @bara suggéré + créé une branche de sauvegarde locale

# Rewind to commit just before the pushed-and-amended one.
# Replace <hash> with the needed hash.
# --soft means: leave all the changes there, so nothing is lost.
git reset --soft <hash>

# Create new branch, just for a backup, still having all changes in it.
# The branch was feature/1234, new one - feature/1234-gone-bad
git checkout -b feature/1234-gone-bad

# Commit all the changes (all the mess) not to lose it & not to carry around
git commit -a -m "feature/1234 backup"

# Switch back to the original branch
git checkout feature/1234

# Pull the from remote (named 'origin'), thus 'repairing' our main problem
git pull origin/feature/1234

# Now you have a clean-and-non-diverged branch and a backup of the local changes.
# Check the needed files from the backup branch
git checkout feature/1234-gone-bad -- the/path/to/file.php

peut-être que ce n'est pas une solution rapide et propre, et j'ai perdu mon histoire (1 commit au lieu de 5), mais il a sauvé le travail d'une journée.

7
répondu davisca 2017-10-08 10:31:00

si vous savez que personne n'a retiré votre commit non modifié, utilisez l'option --force-with-lease de git push .

dans TortoiseGit, vous pouvez faire la même chose sous "Push..."options" Force: peut rejeter "et en cochant"changements connus".

Force (peut rejeter des changements connus) permet au dépôt distant d'accepter une poussée plus sûre non-fast-forward. Cela peut causer la perte des propagations du dépôt distant; utilisez-le avec soins. Cela peut empêcher de perdre des changements inconnus des autres personnes sur la télécommande. Il vérifie si la branche server pointe vers la même propagation que la branche de suivi à distance (modifications connues). Si oui, une poussée de force sera effectuée. Sinon il sera rejeté. Puisque git n'a pas de tags de suivi à distance, les tags ne peuvent pas être réécrits en utilisant cette option.

4
répondu ShawnFeatherly 2017-10-08 10:35:29

si vous n'avez pas poussé le code sur votre branche distante (Github/Bitbucket), vous pouvez modifier le message de propagation sur la ligne de commande comme ci-dessous.

 git commit --amend -m "Your new message"

Si vous travaillez sur une branche spécifique, faites ceci:

git commit --amend -m "BRANCH-NAME: new message"

si vous avez déjà poussé le code avec un message erroné, vous devez faire attention en changeant le message. I. e après que vous avez changé le message de propagation et essayé de le pousser de nouveau, vous finissez par avoir des problèmes. Faire il lisse suivre les étapes suivantes.

Merci de lire l'intégralité de la réponse avant de le faire

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

Note importante: lorsque vous utilisez la force push directement, vous pourriez vous retrouver avec des problèmes de code que d'autres développeurs travaillent sur la même branche. Donc, pour éviter ces conflits, vous avez besoin de tirer le code de votre branche avant de faire le force push :

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

C'est la meilleure pratique pour changer le message de propagation, s'il a déjà été poussé.

3
répondu Prabhakar 2017-10-08 10:33:09

voici un moyen très simple et propre pour pousser vos modifications après que vous avez déjà fait un git add "your files" et git commit --amend :

git push origin master -f

ou:

git push origin master --force
2
répondu Marwen Bkh 2016-06-09 19:38:29

vous obtenez cette erreur parce que la télécommande Git possède déjà ces fichiers de propagation. Vous devez forcer la branche pour que cela fonctionne:

git push -f origin branch_name

assurez-vous également de tirer le code à distance comme quelqu'un d'autre dans votre équipe pourrait avoir poussé à la même branche.

git pull origin branch_name

C'est l'un des cas où nous devons forcer la propagation à distance.

2
répondu Praveen Dhawan 2017-10-08 10:34:39

j'ai dû résoudre ce problème avec le fait de tirer de la prise en compte à distance et de traiter les conflits de fusion qui ont surgi, commit puis push. Mais j'ai l'impression qu'il y a un meilleur moyen.

1
répondu Spoike 2008-10-31 11:39:28

j'ai juste continué à faire ce que Git m'a dit de faire. So:

  • ne peut pas pousser à cause de commit modifié.
  • je fais une traction comme suggéré.
  • la fusion échoue. donc je le Répare manuellement.
  • créer un nouveau commit (étiqueté "fusionner") et poussez-le.
  • ça a l'air de marcher!

Note: la Commission modifiée est la plus récente.

1
répondu Rolf 2017-10-08 10:35:55