Question

Quand j'ai un peu travaillé avec mon code source, j'ai fait mon commit habituel, puis j'ai poussé vers un référentiel distant. Mais ensuite, j'ai remarqué que j'avais oublié d'organiser mes importations dans le code source. Alors je fais la commande amende pour remplacer le commit précédent:

> git commit --amend

Malheureusement, la validation ne peut pas être repoussée dans le référentiel. 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 référentiel distant.)

Était-ce utile?

La solution

En fait, une fois, j'ai poussé avec --force et .git référentiel 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 faites 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 que vous ayez poussé le commit modifié avec --force (ou + master).

  1. Utilisez git reflog pour trouver l'ancien commit que vous avez modifié (appelez-le old et nous appellerons le nouveau commit que vous avez créé en modifiant new).
  2. Créez une fusion entre git checkout new && git merge -s ours old et git merge master en enregistrant l'arborescence de git push . HEAD:master, comme <=>.
  3. Fusionner cela à votre maître avec <=>
  4. Mettez à jour votre maître avec le résultat avec <=>
  5. Diffusez le résultat.

Ensuite, les personnes qui ont eu la malchance de fonder leur travail sur le commit que vous avez effacé en modifiant et en forçant une impulsion verront la fusion résultante verront que vous favorisez <=> par <=>. Leurs fusions ultérieures ne verront pas les conflits entre <=> et <=> résultant de votre modification, ils ne devront donc pas en souffrir.

Autres conseils

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 que l'un d'eux s'en rende compte.

Si vous savez que vous êtes la seule personne à pousser et que vous voulez appliquer un commit modifié ou un commit qui retourne 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 à l'extrémité distante 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 façon 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 sur le référentiel local et remote_ref le nom de la branche sur le référentiel distant. Cette paire de commandes utilise deux raccourcis. :master a une référence_local locale nulle, ce qui signifie de pousser une branche nulle vers le côté distant master, c’est-à-dire supprimer la branche distante. Un nom de branche sans : signifie que vous envoyez la branche locale portant le nom donné à la branche distante portant le même nom. master:master dans cette situation est un raccourci pour <=>.

Rant 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 Git.

Quoi qu'il en soit, le " évident " Pour ce faire, en supposant que vous n’ayez pas essayé de forcer la poussée, vous tirez d’abord. Cela tire le changement que vous avez modifié (et donc n’avez plus) pour que vous l’ayez à nouveau.

Une fois que vous avez résolu tous les conflits, vous pouvez appuyer à nouveau.

Donc:

git pull

Si vous obtenez des erreurs lors de l'extraction, il se peut 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

Vous obtiendrez peut-être un commit supplémentaire indiquant au sujet une & "; fusion Triviale &";.

.

Réponse courte: N'envoyez pas les commits modifiés à un rapport public.

Réponse longue: quelques commandes Git, telles que git commit --amend et git rebase, réécrivent le graphe d'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 tromper avec l’historique, car si quelqu'un avait déjà vos modifications, il pourrait é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, vraiment pousser un commit modifié, vous pouvez le faire comme ceci:

$ git push origin +master:master

Le premier signe + va forcer la poussée, même si cela ne donne pas un & "avance rapide &"; commettre. (Une validation rapide est effectuée lorsque les modifications que vous appliquez sont un descendant direct des modifications déjà 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:

  • Réinitialisez la tête de branche au commit parent.
  • Cachez ce dernier commit.
  • Forcer le push sur la télécommande. La télécommande n'a pas le dernier commit.
  • Pop votre cachette.
  • S'engager proprement.
  • Push to remote.

N'oubliez pas de changer " origine " et " master " si vous appliquez ceci à une autre branche ou à une autre.

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.

  • Modification accidentelle du dernier commit déjà appliqué
  • Effectué beaucoup de modifications localement, engagé cinq fois
  • J'ai essayé de pousser, eu une erreur, paniqué, fusionné à distance, eu beaucoup de fichiers non-fichiers, poussé, échoué, etc.

En tant que débutant chez Git, j’ai pensé 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 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 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 preuve de prudence lors de la modification du message. 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 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?

Remarque importante: lorsque vous utilisez directement le push 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 de lancer la poussée forcée :

 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 utilisé 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 supprimer " et en vérifiant " les modifications connues ".

  

Forcer (le rejet des modifications connues) autorise le 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é. Puisque git ne possède pas de balises de suivi à distance, les balises ne peuvent pas être écrasées avec cette option.

Voici un moyen très simple et propre d’appliquer vos modifications après avoir effectué un git add "your files" et git commit --amend:

git push origin master -f

ou:

git push origin master --force

Vous obtenez cette erreur car la télécommande Git contient déjà ces fichiers de validation. Vous devez forcer la branche pour que cela fonctionne:

git push -f origin branch_name

Assurez-vous également d'extraire le code de la télécommande, car un autre membre de votre équipe aurait pu le placer dans la même branche.

git pull origin branch_name

C’est l’un des cas dans lequel nous devons forcer la validation du commit sur remote.

Je devais résoudre ce problème en extrayant du référentiel distant et gérer les conflits de fusion qui se présentaient, validaient, puis poussaient. Mais je pense qu’il existe un meilleur moyen.

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

  • Impossible de pousser en raison d'un commit modifié.
  • Je fais un pull comme suggéré.
  • La fusion échoue. donc je le répare manuellement.
  • Créez un nouveau commit (nommé & "; fusionner &";) et appuyez dessus.
  • Cela semble fonctionner!

Remarque: la validation modifiée était la dernière.

Ici, comment j'ai corrigé une édition dans une précédente validation:

  1. Enregistrez votre travail jusqu'à présent.
  2. Cachez vos modifications pour le moment si elles sont effectuées: git stash Votre copie de travail est maintenant propre à l'état de votre dernier commit.
  3. Apportez les modifications et les corrections.
  4. Validez les modifications en " modifiez le " mode: git commit --all --amend
  5. .
  6. 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 par vous-même avec git log et git diff HEAD^

  7. Réappliquez vos modifications stockées, le cas échéant: git stash apply

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top