Jak podzielić ostatni commit na dwa w Git
Mam dwie działające gałęzie, master i forum i właśnie wprowadziłem kilka modyfikacji w gałęzi forum , które chciałbym wybrać do master . Ale niestety, commit, który chcę wybrać, zawiera również pewne modyfikacje, których nie chcę.
Rozwiązaniem byłoby usunięcie błędnego commita i zastąpienie go dwoma osobnymi commitami, jednym ze zmianami, które chcę wybrać w master, a innymi, które nie należą tam.
Próbowałem robić
git reset --hard HEAD^
Który usunął wszystkie zmiany, więc musiałem wrócić z
git reset ORIG_HEAD
Więc moje pytanie brzmi: jaki jest najlepszy sposób na podzielenie ostatniego commita na dwa oddzielne commity?
8 answers
Powinieneś użyć indeksu. Po wykonaniu mieszanego resetu ("Git reset HEAD^"), dodaj pierwszy zestaw zmian w indeksie, a następnie zatwierdź je. Następnie zatwierdź odpoczywaj.
Możesz użyć "git add " aby umieścić wszystkie zmiany w pliku w indeksie. Jeśli nie chcesz umieszczać każdej modyfikacji w pliku, tylko niektóre z nich, ty można użyć "git add-p".
Zobaczmy przykład. Załóżmy, że miałem plik o nazwie myfile, który zawiera następujące tekst:something
something else
something again
Zmodyfikowałem go w moim ostatnim commicie tak, że teraz wygląda tak:
1
something
something else
something again
2
Teraz decyduję, że chcę podzielić ją na dwie części i chcę wstawić pierwszy wiersz, który ma być w pierwszym zatwierdzeniu, a wstawianie ostatniego wiersza, który ma być w drugim commit.
Najpierw wracam do rodzica HEAD ' a, ale chcę zachować modyfikacje w systemie plików, więc używam "Git reset" bez argumentu (co zrobi tzw. " mixed" "reset"): {]}
$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2
Teraz używam "git add-p" aby dodać zmiany, które chcę zatwierdzić do indeksu (=I etapie). "git add-p" jest interaktywnym narzędziem, które pyta o to, co zmiany w pliku, jeśli zostanie dodany do indeksu.
$ git add -p myfile
diff --git a/myfile b/myfile
index 93db4cb..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,5 @@
+1
something
something else
something again
+2
Stage this hunk [y,n,a,d,/,s,e,?]? s # split this section into two!
Split into 2 hunks.
@@ -1,3 +1,4 @@
+1
something
something else
something again
Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y # yes, I want to stage this
@@ -1,3 +2,4 @@
something
something else
something again
+2
Stage this hunk [y,n,a,d,/,K,g,e,?]? n # no, I don't want to stage this
Wtedy zatwierdzam tą pierwszą zmianę:
$ git commit -m "Added first line"
[master cef3d4e] Added first line
1 files changed, 1 insertions(+), 0 deletions(-)
Teraz mogę zatwierdzić wszystkie inne zmiany (mianowicie cyfrę "2" umieszczoną w ostatniej linijce):
$ git commit -am "Added last line"
[master 5e284e6] Added last line
1 files changed, 1 insertions(+), 0 deletions(-)
Sprawdźmy log, aby zobaczyć jakie commity mamy:
$ git log -p -n2 | cat
Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8
Author: ...
Date: ...
Added last line
Diff --git a/myfile b/myfile
Index f9e1a67..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -2,3 +2,4 @@
something
something else
something again
+2
Commit cef3d4e0298dd5d279a911440bb72d39410e7898
Author: ...
Date: ...
Added first line
Diff --git a/myfile b/myfile
Index 93db4cb..f9e1a67 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,4 @@
+1
something
something else
something again
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
2012-10-25 12:44:08
Bramki:
- chcę podzielić poprzedni commit (
splitme
) na dwa. - chcę utrzymać komunikat commit.
Plan:
- rebase interactive from one before
splitme
. - edit
splitme
. - Zresetuj pliki, aby podzielić je na drugi commit.
- Zmień commit, zachowując wiadomość, zmodyfikuj w razie potrzeby.
- Dodaj z powrotem pliki rozdzielone od pierwszego commita.
- Commit z nową wiadomością.
- Kontynuuj rebase.
Kroki rebase (1 i 7) można pominąć, jeśli splitme
jest ostatnim zatwierdzeniem.
git rebase -i splitme^
# mark splitme commit with 'e'
git reset HEAD^ -- $files
git commit --amend
git add $files
git commit -m "commit with just some files"
git rebase --continue
Jeśli chciałbym, aby split files był najpierw zatwierdzony, potem ponownie przełączyłbym kolejność
git rebase -i splitme^
# swap order of splitme and 'just some files'
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
2014-09-27 20:55:15
Aby zmienić bieżący commit na dwa commity, możesz zrobić coś takiego jak poniżej.
Albo:
git reset --soft HEAD^
To wycofuje ostatni commit, ale pozostawia wszystko zainscenizowane. Następnie możesz usunąć określone pliki:
git reset -- file.file
Opcjonalnie Przywróć części tych plików:
git add -p file.file
Utwórz nowy pierwszy commit:
git commit
Etap i zatwierdź resztę zmian w drugim commicie:
git commit -a
Lub:
Cofanie i cofanie wszystkich zmian z ostatniego commita:
git reset HEAD^
Selektywnie zaplanuj pierwszą rundę zmian:
git add -p
Commit:
git commit
Zatwierdź resztę zmian:
git commit -a
(w każdym kroku, jeśli usunąłeś commit, który dodał nowy plik i chcesz dodać go do drugiego commita, będziesz musiał ręcznie dodać go jako commit -a
tylko etapy zmian do już śledzonych plików.)
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
2009-09-17 21:13:25
Uruchom git gui
, wybierz przycisk radiowy "Zmień Ostatnie zatwierdzenie" i odinstaluj (Zatwierdź > Odinstaluj z zatwierdzenia lub Ctrl-U) zmiany, których nie chcesz wprowadzać do pierwszego commita. Myślę, że to najłatwiejszy sposób.
Kolejną rzeczą, którą możesz zrobić, to wybrać zmianę bez zatwierdzania (git cherry-pick -n
), a następnie ręcznie lub za pomocą git gui
wybrać pożądane zmiany przed zatwierdzeniem.
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
2014-02-04 03:37:19
git reset HEAD^
Trudne jest to, co zabija twoje zmiany.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
2009-09-17 16:58:42
Dziwi mnie, że nikt nie zasugerował. Spowoduje to wprowadzenie zmian z ostatniego commita forum
, ale ich nie zatwierdzi - możesz wtedy reset
usunąć zmiany, których nie potrzebujesz i zatwierdzić To, co chcesz zachować.
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
2011-12-12 22:12:41
Metoda double-revert-squash
- wykonaj kolejny commit, który usuwa niepożądane zmiany. (Jeśli jest na plik, to jest to naprawdę proste:
git checkout HEAD~1 -- files with unwanted changes
igit commit
. Jeśli nie, pliki z mieszanymi zmianami mogą być częściowo zainscenizowanegit reset file
igit add -p file
jako etap pośredni.) Nazwij to revert . -
git revert HEAD
- wykonaj kolejny commit, który doda niepożądane zmiany. To jest double-revert - z 2 commitów, które teraz wykonałeś, pierwszy na commit to split (
git rebase -i HEAD~3
). Ten commit staje się teraz wolny od niechcianych zmian, ponieważ są one w drugim commicie.
Korzyści
- zachowuje komunikat commit
- działa nawet jeśli commit do split nie jest ostatnim. Wymaga tylko, aby niepożądane zmiany nie były sprzeczne z późniejszymi commitami
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-07-06 15:33:57
Skoro jesteś cherry-picking, możesz:
-
cherry-pick
z dodaną opcją--no-commit
. -
reset
i używaćadd --patch
,add --edit
lub po prostuadd
, aby ustawić to, co chcesz zachować. -
commit
inscenizowane zmiany.- aby ponownie użyć oryginalnej wiadomości zatwierdzającej, możesz dodać opcje
--reuse-message=<old-commit-ref>
lub--reedit-message=<old-commit-ref>
do poleceniacommit
.
- aby ponownie użyć oryginalnej wiadomości zatwierdzającej, możesz dodać opcje
- zdmuchnij niezakłócone zmiany za pomocą
reset --hard
.
W inny sposób, zachowując lub edytując oryginalny commit wiadomość:
-
cherry-pick
oryginalny commit jak zwykle. - Odwróć zmiany, których nie chcesz i użyj
add
, aby ustawić odwrócenie.- ten krok byłby łatwy, jeśli usuwasz to, co dodałeś, ale trochę trudny, jeśli dodajesz to, co usunąłeś lub cofasz zmianę.
-
commit --amend
w celu wywołania odwrócenia na commit cherry-picked.- otrzymasz ponownie ten sam komunikat commit, który możesz zachować lub zmienić jako konieczne.
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-04-08 04:22:23