Czy mogę usunąć commit z Gita, ale zachować zmiany?
W jednej z moich gałęzi programistycznych wprowadziłem kilka zmian w mojej bazie kodowej. Zanim udało mi się ukończyć funkcje, nad którymi pracowałem, musiałem przełączyć moją bieżącą gałąź na master, aby demo niektórych funkcji. Ale samo użycie "Git checkOut master" zachowało zmiany, które również wprowadziłem w swojej gałęzi deweloperskiej, tym samym łamiąc część funkcjonalności w master. Więc to, co zrobiłem, to zatwierdzić zmiany w mojej gałęzi rozwoju z Komunikatem commit "tymczasowy commit", a następnie checkout mistrz dema.
Teraz, gdy skończyłem z demem I wróciłem do pracy nad moją gałęzią programistyczną, chciałbym usunąć "tymczasowy commit", który zrobiłem, zachowując jednocześnie wprowadzone zmiany. Czy to możliwe?
11 answers
To takie proste:
git reset HEAD^
Uwaga: niektóre powłoki traktują ^
jako znak specjalny (na przykład niektóre powłoki Windows lub ZSH z włączonym globbingiem ), więc być może będziesz musiał zacytować "HEAD^"
w takich przypadkach.
git reset
Bez --hard
lub --soft
przenosi HEAD
do wskazanego commita, bez zmiany plików. HEAD^
odnosi się do (pierwszego) nadrzędnego commita bieżącego commita, który w Twoim przypadku jest commitem przed tymczasowym.
Zauważ, że inną opcją jest kontynuowanie pracy normalnie, a następnie w następnym punkcie zatwierdzania Uruchom:
git commit --amend [-m … etc]
Który zamiast edytuje najnowszy commit, mając taki sam efekt jak powyżej.
Zauważ, że to (jak w przypadku prawie każdej odpowiedzi Gita) może powodować problemy, jeśli już wypchnąłeś zły commit do miejsca, z którego ktoś inny mógł go wyciągnąć. Staraj się tego unikać
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
2020-01-29 13:41:45
Istnieją dwa sposoby radzenia sobie z tym. Co jest łatwiejsze zależy od twojej sytuacji
Reset
Jeśli commit, którego chcesz się pozbyć, był ostatnim commitem, a nie wykonałeś żadnej dodatkowej pracy, możesz po prostu użyć git-reset
git reset HEAD^
Przenosi Twoją gałąź z powrotem do commita tuż przed twoją obecną głową. Jednak w rzeczywistości nie zmienia to plików w roboczym drzewie. W rezultacie zmiany, które były w tym commicie, pojawiają się jako zmodyfikowane-to jak polecenie 'uncommit'. Mam na to pseudonim.
git config --global alias.uncommit 'reset HEAD^'
Wtedy możesz użyć git uncommit
w przyszłości, aby utworzyć kopię zapasową jednego commita.
Zgniatanie
Zgniatanie commita oznacza połączenie dwóch lub więcej commitów w jeden. Robię to dość często. W Twoim przypadku masz już ukończoną funkcję, a następnie zakończysz ją i zatwierdzisz ponownie odpowiednim, trwałym Komunikatem zatwierdzającym.
git rebase -i <ref>
Mówię wyżej, ponieważ chcę to wyjaśnić może to być dowolna liczba commitów. Uruchom git log
i znajdź commit, którego chcesz się pozbyć, skopiuj jego SHA1 i użyj go zamiast <ref>
. Git przeniesie cię w interaktywny tryb rebase. Wyświetli wszystkie commity pomiędzy Twoim obecnym stanem a tym, co umieściłeś w miejscu <ref>
. Więc jeśli <ref>
jest 10 commitów temu, pokaże Ci wszystkie 10 commitów.
Przed każdym commitem pojawi się słowo pick
. Znajdź commit, którego chcesz się pozbyć i zmień go z pick
na fixup
lub squash
. Użycie fixup
po prostu odrzuca, który zatwierdza wiadomość i łączy zmiany z jego bezpośrednim poprzednikiem na liście. Słowo kluczowe squash
robi to samo, ale pozwala edytować komunikat commit nowo połączonego commit.
Zauważ, że commity będą ponownie zatwierdzane w kolejności, w jakiej pojawią się na liście po wyjściu z edytora. Jeśli więc utworzyłeś tymczasowy commit, wykonałeś inną pracę w tej samej gałęzi i ukończyłeś tę funkcję w późniejszym commicie, a następnie używając rebase pozwoli Ci to na ponowne sortowanie commitów i ich zgniatanie.
WARNING:
Rebasing modyfikuje historię-nie rób tego dla commitów, które już udostępniłeś innym programistom.
Stashing
W przyszłości, aby uniknąć tego problemu, rozważ użycie git stash
do tymczasowego przechowywania niezatwierdzonych prac.
git stash save 'some message'
To zapisze Twoje bieżące zmiany na stronie listy skrytek. Powyżej jest najbardziej wyraźna wersja Komenda stash, pozwalająca na komentarz opisujący co ukrywasz. Możesz również po prostu uruchomić git stash
i nic więcej, ale żadna wiadomość nie zostanie zapisana.
Możesz przeglądać swoją listę skrytek...
git stash list
To pokaże Ci wszystkie Twoje staszki, na jakich gałęziach zostały zrobione, wiadomość i początek każdej linii oraz identyfikator tego skrytki, który wygląda tak stash@{#}
gdzie # jest jego pozycją w tablicy stosów.
Aby przywrócić skrytkę (która może być wykonane na dowolnej gałęzi, niezależnie od tego, gdzie pierwotnie został utworzony stash) po prostu uruchom...
git stash apply stash@{#}
Ponownie, tam # jest pozycja w tablicy stashes. Jeśli schowek, który chcesz przywrócić, znajduje się w pozycji 0
- to znaczy, jeśli był to najnowszy Schowek. Następnie możesz po prostu uruchomić polecenie bez podawania pozycji stash, git założy, że masz na myśli ostatnią: git stash apply
.
Więc, na przykład, jeśli znajdę się pracując na niewłaściwej gałęzi - mogę uruchomić następujące Sekwencja poleceń.
git stash
git checkout <correct_branch>
git stash apply
W Twoim przypadku poruszałeś się po gałęziach trochę więcej, ale ten sam pomysł nadal obowiązuje.
Mam nadzieję, że to pomoże.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
2018-05-17 12:32:25
Myślę, że szukasz tego
git reset --soft HEAD~1
Wycofuje najnowszy commit, zachowując zmiany wprowadzone w tym commicie w inscenizacji.
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
2019-01-23 02:38:40
Tak, możesz usunąć swój commit bez usuwania zmian:
git reset @~
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
2020-11-19 17:07:17
Szukasz albo git reset HEAD^ --soft
albo git reset HEAD^ --mixed
.
Istnieją 3 tryby polecenia reset, jak podano w docs:
git reset HEAD^ --soft
Cofnij git commit
. Zmiany nadal istnieją w drzewie roboczym(folderze projektu) + indeksie (--cached)
git reset HEAD^ --mixed
Cofnij git commit
+ git add
. Zmiany nadal istnieją w działającym drzewie
git reset HEAD^ --hard
Jakbyś nigdy nie wprowadził tych zmian w bazie kodowej. Zmiany zniknęły z pracujące drzewo.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
2019-06-06 11:22:58
W moim przypadku, już przesunąłem się do repo. AUĆ!
Możesz przywrócić określony commit, zachowując zmiany w lokalnych plikach, wykonując:
git revert -n <sha>
W ten sposób udało mi się zachować potrzebne zmiany i usunąć commit, który został już wypchnięty.
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-05-18 14:20:22
2020 prosty sposób:
git reset <commit_hash>
(hash commit ostatniego commita, który chcesz zachować).
Jeśli commit został wypchnięty, możesz wykonać :
git push -f
Zachowasz teraz niezakontraktowane zmiany lokalnie
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
2020-06-04 17:51:37
Dla tych, którzy używają zsh, musisz użyć:
git reset --soft HEAD\^
Wyjaśnione tutaj: https://github.com/robbyrussell/oh-my-zsh/issues/449
W przypadku, gdy URL stanie się martwy, ważną częścią jest:
Escape the ^ in your command
Możesz alternatywnie użyć HEAD~ , abyś nie musiał uciekać przed nim za każdym razem.
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
2020-06-20 09:12:55
Używanie git 2.9 (dokładnie 2.9.2.okna.1)
git reset HEAD^
podpowiada więcej; nie wiem, czego tu oczekujemy. Proszę zapoznać się z poniższym zrzutem ekranu
Znaleziono inne rozwiązanie git reset HEAD~#numberOfCommits
za pomocą którego możemy wybrać liczbę lokalnych commitów, które chcesz zresetować, zachowując swoje zmiany w stanie nienaruszonym. W związku z tym mamy możliwość odrzucenia wszystkich lokalnych commitów, jak również ograniczonej liczby lokalnych commitów.
Patrz poniżej zrzuty ekranu pokazujące git reset HEAD~1
w działanie:
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-22 10:03:54
Jeszcze jeden sposób.
Dodaj commit na górze tymczasowego commita, a następnie wykonaj:
git rebase -i
Aby połączyć dwa commity w jeden (polecenie otworzy plik tekstowy z wyraźnymi instrukcjami, edytuje go).
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
2013-04-02 19:59:54
W niektórych przypadkach chcę tylko cofnąć zmiany w określonych plikach w pierwszym zatwierdzeniu, aby dodać je do drugiego zatwierdzania i mieć czystszy dziennik git.
W tym przypadku, to co robię jest następujące:
git checkout HEAD~1 <path_to_file_to_put_in_different_commit>
git add -u
git commit --amend --no-edit
git checkout HEAD@{1} <path_to_file_to_put_in_different_commit>
git commit -m "This is the new commit"
Oczywiście działa to dobrze nawet w środku rebase -i
z opcją edycji na commit to split.
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
2020-06-12 07:09:17