Question Comment puis-je transférer la validation modifiée vers le référentiel Git distant?


Quand j'ai travaillé un peu avec mon code source, j'ai fait mon truc habituel et je l'ai poussé vers un dépôt distant. Mais j'ai remarqué que j'avais oublié d'organiser mes importations dans le code source. Donc, je fais la commande modifier pour remplacer le commit précédent:

> git commit --amend

Malheureusement, le commit ne peut pas être repoussé dans 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 devrais-je faire? (Je peux accéder au référentiel distant.)


525
2017-10-31 10:23


origine


Réponses:


J'ai en fait une fois poussé avec --force et .git dépôt et grondé par Linus TEMPS FORT. En général, cela va créer 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 de toute façon, alors je ne vais pas les répéter ici. Mais voici une astuce pour se remettre de la situation après vous avez rejeté le commit modifié avec --force (ou + master).

  1. Trouvez 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éer une fusion entre old et new, en enregistrant l'arbre de new, comme git checkout new && git merge -s ours old.
  3. Fusionner cela avec votre maître avec git merge master
  4. Mettez à jour votre maître avec le résultat avec git push . HEAD:master
  5. Poussez le résultat sur.

Ensuite, les gens qui ont eu la malchance d'avoir basé leur travail sur l'engagement que vous avez effacé en modifiant et en forçant une poussée (qui est tu es un très mauvais garçon) verra la fusion résultante verra que vous favorisez new plus de old. Leurs fusions plus tard ne verront pas les conflits entre old et new cela résulte de votre amendement, afin qu'ils n'aient pas à souffrir.


409
2018-01-11 07:36



Vous voyez une fonctionnalité de sécurité Git. Git refuse de mettre à jour la branche distante avec votre branche, car la validation de tête de votre branche n'est pas un descendant direct de la validation en cours 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 avait un nouvel engagement entrant en même temps et celui qui poussait le dernier perdrait le travail du précédent pousseur sans l'un ou l'autre. les réalisant cela.

Si vous savez que vous êtes la seule personne à pousser et que vous voulez pousser un commit modifié ou pousser un commit qui enroule la branche, vous pouvez 'forcer' Git à mettre à jour la branche distante en utilisant le -f commutateur.

git push -f origin master

Même cela peut ne pas fonctionner car Git permet aux dépôts distants de refuser les push non-fastforward à 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 ou, en tant que bidouille sale, supprimer et recréer la branche:

git push origin :master
git push origin master

En général, le dernier paramètre à 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 est le nom de la branche sur le référentiel distant. Cette paire de commandes utilise deux raccourcis. :mastera un null local_ref 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 pousser la branche locale avec le nom donné à la branche distante avec le même nom. master dans cette situation est courte pour master:master.


239
2017-10-31 21:58



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

Quoi qu'il en soit, la façon "évidente" de le faire, en supposant que vous n'ayez pas essayé de forcer la poussée, est de tirer en premier. Cela tire le changement que vous avez modifié (et donc ne plus avoir) de sorte que vous l'avez à nouveau.

Une fois que vous avez résolu 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 votre configuration de référentiel local (j'ai eu une mauvaise référence dans la section de branche .git / config).

Et après

git push

Peut-être que vous obtiendrez un engagement supplémentaire avec le sujet racontant une «fusion triviale».


191
2017-10-31 14:35



Réponse courte: Ne pas pousser les validations modifiées vers un dépôt public.

Réponse longue: Quelques commandes Git, comme git commit --amend et git rebase, réécrit réellement le graphique de l'histoire. C'est très bien tant que vous n'avez pas publié vos changements, mais une fois que vous le faites, vous ne devriez pas vous tromper avec l'historique, car si quelqu'un a déjà vos changements, alors quand ils essaient de tirer à nouveau, ça peut é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 + Le signe forcera le push à se produire, même s'il ne résulte pas en un commit "fast-forward". (Une validation avant rapide se produit lorsque les modifications que vous appuyez sont un descendant direct des changements déjà dans le repo public.)


90
2018-06-21 14:41



Voici une manière très simple et propre de pousser vos changements 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 branche à la validation parente.
  • Stash ce dernier commit.
  • Force pousser à distance. La télécommande n'a pas le dernier commit.
  • Pop votre cachette.
  • Engagez-vous proprement.
  • Pousser sur la télécommande.

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


36
2017-09-24 15:46



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
2018-02-20 10:24



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

  • Accidentellement modifié le dernier commit qui a déjà été poussé
  • Fait beaucoup de changements localement, commis cinq fois
  • Je ai essayé de pousser, eu une erreur, paniqué, fusionné à distance, a obtenu beaucoup de non-mes-fichiers, poussé, échoué, etc.

En tant que novice Git, je pensais que c'était complet FUBAR.

Solution: Un peu comme suggéré par @bara + création d'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 historique (1 commit au lieu de 5), mais cela a sauvé une journée de travail.


7
2018-06-07 00:03



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

Dans TortoiseGit, vous pouvez faire la même chose sous les options "Push ..." "Forcer: Peut être rejeté" et vérifier "les changements connus".

Force (peut annuler les modifications connues) permet au référentiel distant d’accepter un push plus rapide Cela peut entraîner la perte de validations du référentiel distant; utilisez-le avec soin. 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 de force sera effectuée. Sinon, il sera rejeté. Comme git ne possède pas de balises de suivi à distance, les balises ne peuvent pas être remplacées à l'aide de cette option.


4
2018-01-18 08:29



Voici une manière très simple et propre de pousser vos changements 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
2018-01-13 07:20