web-dev-qa-db-fra.com

Comment puis-je envoyer le commit modifié dans le référentiel Git distant?

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.)

605
Spoike

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).

  1. Utilisez git reflog pour trouver l'ancien commit que vous avez modifié (appelez-le old et nous appellerons le nouveau commit créé en modifiant new).
  2. Créez une fusion entre old et new, en enregistrant l’arborescence de new, comme git checkout new && git merge -s ours old.
  3. Fusionner cela à 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.

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.

468
gitster

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.

256
CB Bailey

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".

206
Tim Band

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.)

97
mipadi

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éinitialiser la tête de branche au commit parent.
  • Cachez ce dernier commit.
  • Force Push to remote. La télécommande n'a pas maintenant le dernier commit.
  • Pop votre cachette.
  • S'engager proprement.
  • Push to remote.

N'oubliez pas de changer "Origine" et "Maître" si vous appliquez cela à une autre branche ou à une autre télécommande.

44
Faiza

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
21
bara

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

  • Modification accidentelle du dernier commit déjà poussé
  • Fait beaucoup de changements localement, engagé cinq fois
  • Essayé de pousser, eu une erreur, paniqué, fusionné à distance, eu beaucoup de fichiers non-mes-fichiers, poussé, échoué, etc.

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.

7
davisca

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é.

5
Prabhakar

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.

5
ShawnFeatherly

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.

3
Praveen Dhawan

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
2
craken

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.

1
Spoike

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

  • Ne peut pas pousser à cause de commit modifié.
  • Je fais un pull comme suggéré.
  • La fusion échoue. alors je le répare manuellement.
  • Créez un nouveau commit (intitulé "merge") et appuyez dessus.
  • Cela semble fonctionner!

Remarque: le commit modifié était le dernier.

1
Rolf

Ici, comment j'ai corrigé une édition dans un commit précédent:

  1. Enregistrez votre travail jusqu'à présent.
  2. Rangez vos modifications pour l'instant si elles sont effectuées: git stash Maintenant, votre copie de travail est propre à l'état de votre dernier commit.
  3. Apportez les modifications et les corrections.
  4. Validez les modifications en mode "amende": git commit --all --amend
  5. 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^

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

0
Harshal Wani