Jak wcisnąć zmieniony commit do zdalnego repozytorium Git?

Kiedy pracowałem trochę z moim kodem źródłowym, zrobiłem swoje zwykłe commit, a następnie pchnąłem do zdalnego repozytorium. Ale potem zauważyłem, że zapomniałem zorganizować mój import w kodzie źródłowym. Wykonuję więc polecenie amend, aby zastąpić poprzedni commit:

> git commit --amend

Niestety commit nie może zostać przeniesiony z powrotem do repozytorium. Jest odrzucany w ten sposób:

> 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/'
Co mam zrobić? (Mogę uzyskać dostęp do zdalnego repozytorium.)
Author: Peter Mortensen, 2008-10-31

13 answers

Faktycznie raz pchnąłem z --force i .git repozytorium i zostałem skarcony przez Linusa BIG TIME . Ogólnie rzecz biorąc, stworzy to wiele problemów dla innych ludzi. Prosta odpowiedź brzmi: "nie rób tego".

Widzę, że inni i tak dali przepis na to, więc nie będę ich tu powtarzał. Ale tutaj jest wskazówka, aby wyzdrowieć z sytuacji po wypchnąłeś zmieniony commit za pomocą --force (lub +master).

  1. Znajdź Stary commit, który zmieniłeś (nazwij go old, i wywołamy nowy commit utworzony przez zmianę new).
  2. Utwórz połączenie pomiędzy old i new, rejestrując drzewo new, Jak git checkout new && git merge -s ours old.
  3. Połącz to ze swoim mistrzem z git merge master
  4. Zaktualizuj swój master o wynik za pomocą git push . HEAD:master
  5. wypchnij wynik.

Potem ludzie, którzy byli na tyle nieszczęśliwi, że oparli swoją pracę na commicie, który zniszczyłeś, zmieniając i wymuszając push (czyli jesteś bardzo złym boy ) zobaczy powstałe połączenie zobaczy, że faworyzujesz new nad old. Ich późniejsze połączenia nie zauważą konfliktów między old i new, które wynikły z Twojej zmiany, więc nie muszą cierpieć.

 421
Author: 4444,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-09 20:16:36

Widzisz funkcję bezpieczeństwa Git. Git odmawia aktualizacji zdalnej gałęzi z Twoją gałęzią, ponieważ head commit Twojej gałęzi nie jest bezpośrednim potomkiem bieżącego Head commit gałęzi, do której dążysz.

Gdyby tak nie było, to dwie osoby pchające się do tego samego repozytorium mniej więcej w tym samym czasie nie wiedziałyby, że w tym samym czasie wchodzi nowy commit i ktokolwiek pchnął ostatni, straciłby pracę poprzedniego pchającego bez żadnego z nich. zdają sobie z tego sprawę.

Jeśli wiesz, że jesteś jedyną osobą naciskającą i chcesz wcisnąć zmieniony commit lub wcisnąć commit, który cofnie gałąź, możesz "zmusić" Git do zaktualizowania zdalnej gałęzi za pomocą przełącznika -f.

git push -f origin master

Nawet to może nie działać, ponieważ Git pozwala zdalnym repozytoriom na odrzucenie nie-fastforward push na drugim końcu za pomocą zmiennej konfiguracyjnej receive.denynonfastforwards. W takim przypadku powód odrzucenia będzie wyglądał tak (zwróć uwagę na "remote rejected" część):

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

Aby to obejść, musisz zmienić konfigurację zdalnego repozytorium lub jako brudny hack możesz usunąć i odtworzyć gałąź w ten sposób:

git push origin :master
git push origin master

Ogólnie ostatni parametr git push używa formatu <local_ref>:<remote_ref>, Gdzie local_ref jest nazwą gałęzi w repozytorium lokalnym, a remote_ref jest nazwą gałęzi w repozytorium zdalnym. Ta para poleceń używa dwóch skrótów. :master ma null local_ref co oznacza, że przesuwa gałąź null na odległą stronę master, czyli Usuń zdalną gałąź. Nazwa gałęzi bez : oznacza przesunięcie lokalnej gałęzi o podanej nazwie do zdalnej gałęzi o tej samej nazwie. master w tej sytuacji jest skrótem od master:master.

 241
Author: CB Bailey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:24:21

Szybki rant: fakt, że nikt nie zamieścił tutaj prostej odpowiedzi świadczy o desperackiej wrogości użytkowników wykazywanej przez git CLI.

W każdym razie, "oczywistym" sposobem, aby to zrobić, zakładając, że nie próbowałeś wymusić pchnięcia, jest pociągnięcie najpierw. To pociąga za sobą zmianę, którą zmieniłeś (a więc już nie masz), aby mieć ją ponownie.

Po rozwiązaniu wszelkich konfliktów, możesz ponownie nacisnąć.

Więc:

git pull

Jeśli masz błędy w pull, może coś jest nie tak w konfiguracji lokalnego repozytorium (miałem zły ref w .sekcja gałęzi git/config).

I po

git push

Może dostaniesz dodatkowy commit z tematem mówiącym o"trywialnym połączeniu".

 194
Author: GabrieleV,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:27:16

Krótka odpowiedź: nie naciskaj zmienionych zobowiązań do publicznego repo.

Długa odpowiedź: kilka komend Gita, takich jak git commit --amend i git rebase, faktycznie przepisuje wykres historii. Jest to w porządku tak długo, jak nie opublikowałeś swoich zmian, ale kiedy to zrobisz, naprawdę nie powinieneś kręcić się wokół historii, ponieważ jeśli ktoś już dostał twoje zmiany, to kiedy spróbuje wyciągnąć ponownie, może się to nie udać. Zamiast zmieniać commit, powinieneś po prostu utworzyć nowy commit wraz ze zmianami.

Jednakże, jeśli naprawdę, naprawdę chcesz wcisnąć zmieniony commit, możesz to zrobić w następujący sposób:

$ git push origin +master:master

Znak wiodący + wymusi wypchnięcie, nawet jeśli nie spowoduje zmiany "fast-forward". (Commit fast-forward występuje, gdy zmiany, które naciskasz, są bezpośrednim potomkiem zmian już w publicznym repo.)

 93
Author: mipadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 14:35:12

Oto bardzo prosty i czysty sposób na wypchnięcie zmian po dokonaniu commit --amend:

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

Który wykonuje następujące czynności:

  • Zresetuj nagłówek gałęzi do commita rodzica.
  • Schowaj ten ostatni commit.
  • Force push to remote. Pilot nie ma ostatniego commita.
  • Otwórz Schowek.
  • Commit cleanly.
  • Naciśnij na pilota.

Pamiętaj, aby zmienić "origin" i "master", jeśli zastosujesz to do innej gałęzi lub zdalnie.

 37
Author: Faiza,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-15 21:12:56

Rozwiązałem to odrzucając mój lokalny zmieniony commit i dodając nowe zmiany na górze:

# 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
Author: bara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:28:02

Miałem ten sam problem.

  • przypadkowo zmieniono ostatni commit, który został już wypchnięty
  • zrobiłem wiele zmian lokalnie, popełniłem jakieś pięć razy
  • próbował wcisnąć, dostał błąd, spanikował, połączył zdalne, dostał dużo nie-moich-plików, wypchnął, nie powiódł się, itp.

Jako Git-newbie, myślałem, że to kompletne FUBAR .

Rozwiązanie: trochę jak @bara zasugerował + stworzył lokalną gałąź backupu

# 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

Może to nie jest szybki i czyste rozwiązanie, i straciłem swoją historię (1 commit zamiast 5), ale to uratowało dzień pracy.

 7
Author: davisca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:31:00

Jeśli wiesz, że nikt nie wyciągnął twojego niezmodyfikowanego commita, użyj --force-with-lease opcji git push.

W TortoiseGit możesz zrobić to samo pod "Push..."opcje" Wymuś: może odrzucić "i zaznacz " znane zmiany".

Force (może odrzucić znane zmiany) pozwala zdalnemu repozytorium na akceptację bezpieczniejszego, nieszybkiego pchnięcia do przodu. Może to spowodować utratę commitów przez zdalne repozytorium; używaj go ostrożnie. Może to zapobiec utracie nieznanych zmian od innych osób na zdalnie. Sprawdza, czy gałąź serwera wskazuje na ten sam commit co gałąź zdalnego śledzenia (znane zmiany). Jeśli tak, zostanie wykonane pchnięcie siłą. W przeciwnym razie zostanie odrzucona. Ponieważ git nie posiada znaczników zdalnego śledzenia, znaczniki nie mogą być nadpisywane za pomocą tej opcji.

 4
Author: ShawnFeatherly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:35:29

Jeśli nie wypchnąłeś kodu do zdalnej gałęzi (GitHub / Bitbucket), możesz zmienić komunikat commit w wierszu poleceń, jak poniżej.

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

Jeśli pracujesz nad konkretną gałęzią, zrób to:

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

Jeśli już wypchnąłeś kod z błędną wiadomością, musisz być ostrożny przy zmianie wiadomości. np. po zmianie komunikatu commit i ponownym naciśnięciu go, pojawią się problemy. Aby uczynić go gładkim wykonaj następujące czynności kroki.

Proszę przeczytać całą odpowiedź przed zrobieniem

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

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

Ważna uwaga: Kiedy używasz force push bezpośrednio, możesz skończyć z problemami z kodem, które inni programiści pracują nad tą samą gałęzią. Aby uniknąć tych konfliktów, musisz pobrać kod ze swojej gałęzi przed wykonaniem force push :

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

Jest to najlepsza praktyka przy zmianie komunikatu commit, jeśli został on już wypchnięty.

 3
Author: Prabhakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:33:09

Oto bardzo prosty i czysty sposób na przesunięcie zmian po dokonaniu już git add "your files" i git commit --amend:

git push origin master -f

Lub:

git push origin master --force
 2
Author: Marwen Bkh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-09 19:38:29

Otrzymujesz ten błąd, ponieważ Git remote posiada już te pliki commitów. Musisz wymusić naciśnięcie gałęzi, aby to zadziałało:

git push -f origin branch_name

Upewnij się również, że wyciągasz kod z pilota, ponieważ ktoś inny z twojej drużyny mógł pchnąć go do tej samej gałęzi.

git pull origin branch_name

Jest to jeden z przypadków, w których musimy wymusić wciśnięcie commit do remote.

 2
Author: Praveen Dhawan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:34:39

Musiałem rozwiązać ten problem ściągając ze zdalnego repo i poradzić sobie z konfliktami scalania, które powstały, zatwierdzić, a następnie nacisnąć. Ale czuję, że jest lepszy sposób.

 1
Author: Spoike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-31 11:39:28

Robiłem to, co Git mi kazał. Więc:

  • nie można naciskać ze względu na zmieniony commit.
  • Wykonuję pociągnięcie zgodnie z sugestią.
  • Połączenie nie powiodło się. więc naprawiam to ręcznie.
  • Utwórz nowy commit (oznaczony "merge") i wcisnąć.
  • Wygląda na to, że działa!

Uwaga: zmieniony commit był ostatnim.

 1
Author: Rolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-08 10:35:55