Quand j'ai un peu travaillé avec mon code source, j'ai fait mon commit habituel, puis j'ai poussé vers un dépôt distant. Mais ensuite, j'ai remarqué que j'avais oublié d'organiser mes importations dans le code source. Donc, je fais la commande amende pour remplacer le commit précédent:
> git commit --amend
Malheureusement, le commit ne peut pas être repoussé dans le référentiel. C'est rejeté comme ça:
> 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 devrais-je faire? (Je peux accéder au référentiel distant.)
En fait, une fois, j'ai poussé avec les dépôts --force
et .git
et je me suis fait gronder par Linus BIG TIME. En général, cela créera beaucoup de problèmes pour les autres. Une réponse simple est "ne le fais pas".
Je vois que d’autres ont donné la recette pour le faire, alors je ne les répéterai pas ici. Mais voici un conseil pour sortir de la situation après après avoir sorti le commit modifié avec --force (ou + master).
git reflog
pour trouver l'ancien commit que vous avez modifié (appelez-le old
et nous appellerons le nouveau commit créé en modifiant new
).old
et new
, en enregistrant l’arborescence de new
, comme git checkout new && git merge -s ours old
.git merge master
git Push . HEAD:master
Alors les gens qui ont eu la malchance de fonder leur travail sur le commit que vous effacez en modifiant et en forçant un Push verront que la fusion résultante verra que vous favorisez new
par rapport à old
. Leurs fusions ultérieures ne verront pas les conflits entre old
et new
résultant de votre modification, ils ne devront donc pas souffrir.
Vous voyez une fonctionnalité de sécurité Git. Git refuse de mettre à jour la branche distante avec votre branche, car le responsable de la tâche de votre branche n'est pas un descendant direct du commit actuel de la branche vers laquelle vous souhaitez pousser.
Si ce n’était pas le cas, deux personnes poussant vers le même référentiel à peu près au même moment ne sauraient pas qu’un nouveau commit arrivait au même moment et quiconque poussait en dernier perdrait le travail du pousseur précédent sans l’autre les réalisant cela.
Si vous savez que vous êtes la seule personne qui pousse et que vous souhaitez appliquer une validation modifiée ou une validation validant la branche, vous pouvez "forcer" Git à mettre à jour la branche distante à l'aide du commutateur -f
.
git Push -f Origin master
Même cela pourrait ne pas fonctionner, car Git permet aux référentiels distants de refuser les envois non rapides vers l’extérieur en utilisant la variable de configuration receive.denynonfastforwards
. Si tel est le cas, la raison du rejet ressemblera à ceci (notez la partie "rejetée à distance"):
! [remote rejected] master -> master (non-fast forward)
Pour contourner ce problème, vous devez soit modifier la configuration du référentiel distant, soit vous pouvez supprimer et recréer la branche de la manière suivante:
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 du référentiel local et remote_ref
est le nom de la branche du référentiel distant. Cette paire de commandes utilise deux raccourcis. :master
a une valeur locale_ref nulle, ce qui signifie pousser une branche nulle vers le côté distant master
, c'est-à-dire supprimer la branche distante. Un nom de branche sans :
signifie que Poussez la branche locale portant le nom donné vers la branche distante portant le même nom. master
dans cette situation est l'abréviation de master:master
.
Coup de gueule rapide: le fait que personne n'ait posté la réponse simple ici démontre l'hostilité désespérée des utilisateurs affichée par la CLI de Git.
Quoi qu'il en soit, la façon "évidente" de le faire, en supposant que vous n'avez pas essayé de forcer la Push, est de tirer en premier. Cela tire le changement que vous avez modifié (et donc n’a plus) afin que vous l’ayez à nouveau.
Une fois que vous avez résolu tous les conflits, vous pouvez appuyer à nouveau.
Alors:
git pull
Si vous obtenez des erreurs dans pull, peut-être que quelque chose ne va pas dans la configuration de votre référentiel local (j'avais une mauvaise référence dans la section branche de .git/config).
Et après
git Push
Peut-être obtiendrez-vous un commit supplémentaire avec le sujet qui parle d'une "fusion triviale".
Réponse courte: ne pas pousser les modifications modifiées dans un dépôt public.
Réponse longue: Quelques commandes Git, telles que git commit --amend
et git rebase
, réécrivent en réalité le graphe de l'historique. C’est bien tant que vous n’avez pas publié vos modifications, mais une fois que vous l’avez fait, vous ne devriez vraiment pas vous perdre dans l’historique, car si quelqu'un avait déjà vos modifications, il risquait d’échouer si elles essayaient de tirer à nouveau. . Au lieu de modifier un commit, vous devriez simplement faire un nouveau commit avec les modifications.
Cependant, si vous voulez vraiment pousser un commit modifié, vous pouvez le faire comme ceci:
$ git Push Origin +master:master
Le signe +
initial entraînera le Push, même si cela ne donne pas lieu à une validation "fast-forward". (Une validation rapide est effectuée lorsque les modifications que vous souhaitez appliquer sont un descendant direct des modifications déjà présentes dans le référentiel public.)
Voici un moyen très simple et propre d’appliquer vos modifications après avoir effectué 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:
N'oubliez pas de changer "Origine" et "Maître" si vous appliquez cela à une autre branche ou à une autre télécommande.
Je l'ai résolu en supprimant mon commit local modifié 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
J'ai eu le même problème.
En tant que débutant chez Git, je pensais que c'était complet FUBAR .
Solution: un peu comme @bara a 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 que j'ai perdu mon historique (1 commit au lieu de 5), mais cela a sauvé une journée de travail.
Si vous n'avez pas transmis le code à votre branche distante (GitHub/Bitbucket), vous pouvez modifier le message de validation sur la ligne de commande comme indiqué ci-dessous.
git commit --amend -m "Your new message"
Si vous travaillez sur une branche spécifique, procédez comme suit:
git commit --amend -m "BRANCH-NAME: new message"
Si vous avez déjà inséré le code avec un message erroné, vous devez faire attention lorsque vous le modifiez. C'est-à-dire qu'après avoir modifié le message de validation et réessayé, vous finissez par avoir des problèmes. Pour le rendre lisse, suivez les étapes suivantes.
Veuillez lire la réponse au complet 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?
Remarque importante: Lorsque vous utilisez directement Force Push, vous risquez de rencontrer des problèmes de code que d'autres développeurs travaillent sur la même branche. Donc, pour éviter ces conflits, vous devez extraire le code de votre branche avant d'utiliser le force push:
git commit --amend -m "BRANCH-NAME : your new message"
git pull Origin BRANCH-NAME
git Push -f Origin BRANCH-NAME
Ceci est la meilleure pratique lors de la modification du message de validation, s'il a déjà été poussé.
Si vous savez que personne n'a extrait votre commit non modifié, utilisez l'option --force-with-lease
de git Push
.
Dans TortoiseGit, vous pouvez faire la même chose dans les options "Push ..." "Force: peut supprimer" et cocher "modifications connues".
Forcer (peut ignorer les modifications connues) permet au référentiel distant d'accepter un Push plus sûr, sans avance rapide. Cela peut entraîner la perte de validations du référentiel distant. utilisez-le avec précaution. Cela peut empêcher de perdre des modifications inconnues d'autres personnes sur la télécommande. Il vérifie si la branche du serveur pointe vers la même validation que la branche de suivi à distance (modifications connues). Si oui, une poussée forcée sera effectuée. Sinon, il sera rejeté. Comme git ne possède pas de balises de suivi à distance, les balises ne peuvent pas être écrasées avec cette option.
Vous obtenez cette erreur car la télécommande Git contient déjà ces fichiers de validation. Vous devez forcer Push pour que la branche fonctionne:
git Push -f Origin branch_name
Veillez également à extraire le code de la télécommande, car un autre membre de votre équipe aurait pu le pousser dans la même branche.
git pull Origin branch_name
C'est l'un des cas où nous devons forcer Pousser le commit à distance.
Voici un moyen très simple et propre d’appliquer vos modifications après avoir déjà créé un git add "your files"
et git commit --amend
:
git Push Origin master -f
ou:
git Push Origin master --force
Je devais résoudre ce problème en extrayant du référentiel à distance et en gérant les conflits de fusion survenus, les validations, puis les Push. Mais je pense qu’il existe un meilleur moyen.
J'ai juste continué à faire ce que Git m'a dit de faire. Alors:
Remarque: le commit modifié était le dernier.
Ici, comment j'ai corrigé une édition dans un commit précédent:
git stash
Maintenant, votre copie de travail est propre à l'état de votre dernier commit.git commit --all --amend
Votre éditeur apparaîtra pour vous demander un message de journal (par défaut, l'ancien message de journal). Enregistrez et quittez l'éditeur lorsque vous en êtes satisfait.
Les nouvelles modifications sont ajoutées à l'ancien commit. Voyez vous-même avec git log
et git diff HEAD^
Réappliquez vos modifications stockées, le cas échéant: git stash apply