Podziel poprzedni commit na wiele commitów
Bez tworzenia gałęzi i wykonywania kilku ciekawych prac nad nową gałęzią, czy można rozbić pojedynczy commit na kilka różnych commitów po tym, jak został on zatwierdzony w lokalnym repozytorium?
11 answers
git rebase -i
zrobię to.
Po pierwsze, zacznij od czystego katalogu roboczego: git status
nie powinien pokazywać oczekujących modyfikacji, usunięć ani dodatków.
Aby rozdzielić swój najnowszy commit, najpierw:
$ git reset HEAD~
Teraz commit poszczególnych elementów w zwykły sposób, tworząc tyle commitów, ile potrzebujesz.
Jeśli było dalej na drzewie, to
$ git rebase -i HEAD~3
Gdzie 3
jest liczbą commitów wstecz.
Gdyby było dalej w drzewo niż chcesz policzyć, to
$ git rebase -i 123abcd~
Gdzie 123abcd
jest SHA1 commitu, który chcesz rozdzielić.
Kiedy pojawi się ekran edycji rebase, znajdź commit, który chcesz rozdzielić. Na początku tej linii zamień pick
na edit
(e
W skrócie). Zapisz bufor i zakończ. Rebase zatrzyma się zaraz po zatwierdzeniu, które chcesz edytować. Następnie:
$ git reset HEAD~
Zatwierdzaj elementy pojedynczo w zwykły sposób, tworząc tyle commitów, ile potrzebujesz, wtedy
$ git rebase --continue
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-03-05 18:40:49
From Git-rebase manual (SPLITTING commits section)
W trybie interaktywnym możesz oznaczyć commity akcją "edytuj". Nie musi to jednak oznaczać, że git rebase oczekuje, że wynik tej edycji będzie dokładnie jednym zatwierdzeniem. Rzeczywiście, możesz cofnąć zatwierdzenie lub dodać inne zmiany. To może być użyte do podzielenia commita na dwa:
Uruchom interaktywną rebase z
git rebase -i <commit>^
, gdzie<commit>
jest zatwierdzeniem, które chcesz podzielić. W rzeczywistości, każdy zakres commitów wystarczy, o ile zawiera ten commit.Zaznacz commit, który chcesz podzielić za pomocą akcji "edytuj".
Jeśli chodzi o edycję tego commita, wykonaj
git reset HEAD^
. Efekt polega na tym, że głowica jest przewijana o jeden, A Indeks podąża za nim. Jednak drzewo robocze pozostaje takie samo.Teraz dodaj zmiany do indeksu, które chcesz mieć w pierwszym zatwierdzeniu. Możesz użyć
git add
(ewentualnie interaktywnie) lubgit gui
(lub oba), aby to zrobić.Commit indeks now-current z dowolnym Komunikatem commit jest teraz odpowiedni.
Powtórz dwa ostatnie kroki, aż drzewo robocze będzie czyste.
Kontynuuj rebase za pomocą
git rebase --continue
.
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-10-07 17:53:38
Użyj git rebase --interactive
, aby edytować wcześniejszy commit, Uruchom git reset HEAD~
, a następnie git add -p
, aby dodać kilka, następnie zrobić commit, następnie dodać kilka więcej i zrobić kolejny commit, tyle razy, ile chcesz. Gdy skończysz, Uruchom git rebase --continue
, a będziesz mieć wszystkie commity podzielone wcześniej w swoim stosie.
Ważne : pamiętaj, że możesz bawić się i wprowadzać wszystkie zmiany, które chcesz, i nie musisz się martwić o utratę starych zmian, ponieważ zawsze możesz uruchomić git reflog
, aby znaleźć punkt w swoim projekcie, który zawiera zmiany, które chcesz, (nazwijmy to a8c4ab
), a następnie git reset a8c4ab
.
Oto seria poleceń, aby pokazać, jak to działa:
mkdir git-test; cd git-test; git init
Teraz Dodaj plik A
vi A
Dodaj ten wiersz:
one
git commit -am one
Następnie dodaj ten wiersz do A:
two
git commit -am two
Następnie dodaj ten wiersz do A:
three
git commit -am three
Teraz plik A wygląda tak:
one
two
three
I nasz git log
wygląda następująco (cóż, używam git log --pretty=oneline --pretty="%h %cn %cr ---- %s"
bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one
Powiedzmy, że chcemy podzielić drugi commit, two
.
git rebase --interactive HEAD~2
To wyświetla wiadomość, która wygląda tak:
pick 2b613bc two
pick bfb8e46 three
Zmień pierwszy pick
na e
, aby edytować ten commit.
git reset HEAD~
git diff
pokazuje nam, że właśnie odinstalowaliśmy commit, który zrobiliśmy dla drugiego commita: {]}
diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two
Ustawmy tę zmianę i dodaj "i trzecią" do tej linii w pliku A
.
git add .
Jest to zwykle punkt podczas interaktywnej rebazy, gdzie uruchamiamy git rebase --continue
, ponieważ zwykle chcemy wrócić do naszego stosu commitów, aby edytować wcześniejszy commit. Ale tym razem chcemy stworzyć nowy commit. Więc uciekniemy git commit -am 'two and a third'
. Teraz edytujemy plik A
i dodajemy linię two and two thirds
.
git add .
git commit -am 'two and two thirds'
git rebase --continue
Mamy konflikt z naszym commitem, three
, więc rozwiążmy go: {]}
Zmienimy
one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three
To
one
two and a third
two and two thirds
three
git add .; git rebase --continue
Teraz nasz git log -p
wygląda tak:
commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 13:57:00 2013 -0700
three
diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
one
two and a third
two and two thirds
+three
commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 14:07:07 2013 -0700
two and two thirds
diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
one
two and a third
+two and two thirds
commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 14:06:40 2013 -0700
two and a third
diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two and a third
commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 13:56:40 2013 -0700
one
diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one
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-07-08 15:28:58
Poprzednie odpowiedzi opisywały użycie git rebase -i
do edycji commita, który chcesz podzielić i zatwierdzania go w częściach.
Działa to dobrze podczas dzielenia plików na różne commity, ale jeśli chcesz podzielić zmiany w poszczególnych plikach, musisz wiedzieć więcej.
DostajÄ ... c commit, ktĂłry chcesz podzielić, uĹźywajÄ ... C rebase -i
i oznaczajÄ ... C GO dla edit
, masz dwie opcje.
-
Po użyciu plastra
git reset HEAD~
należy przejść przez plastry indywidualnie użyciegit add -p
, aby wybrać te, które chcesz w każdym commicie Edytuj kopię roboczą, aby usunąć zmiany, których nie chcesz; Zatwierdź ten tymczasowy stan; a następnie przeciągnij pełny commit na następną rundę.
Opcja 2 jest przydatna, jeśli dzielisz duży commit, ponieważ pozwala sprawdzić, czy wersje tymczasowe budują i działają poprawnie w ramach scalania. Odbywa się to w następujący sposób.
Po użyciu rebase -i
i edit
w commit, użycie
git reset --soft HEAD~
Aby cofnąć zatwierdzenie, ale pozostawić zatwierdzone pliki w indeksie. Możesz również wykonać reset mieszany, pomijając --soft, w zależności od tego, jak blisko będzie ostatecznego wyniku początkowego commitu. Jedyną różnicą jest to, czy zaczynasz od wszystkich zmian w poczekalni, czy od nich wszystkich w stanie niezmienionym.
Teraz wejdź i edytuj kod. Możesz usuwać zmiany, usuwać dodane pliki i robić wszystko, co chcesz, aby stworzyć pierwszy commit z serii, której szukasz. Możesz zbuduj go, Uruchom i potwierdź, że masz spójny zestaw źródeł.
Kiedy będziesz zadowolony, Ustaw/Odinstaluj pliki zgodnie z potrzebami (lubię używać git gui
do tego) i zatwierdź zmiany za pomocą interfejsu użytkownika lub linii poleceń
git commit
To pierwszy commit zrobiony. Teraz chcesz przywrócić kopię roboczą do stanu, który miał po podziale commit, tak, że można wziąć więcej zmian do następnego commit. Aby znaleźć sha1 edytowanego commitu, użyj git status
. W pierwszych kilku wierszach stanu zobaczysz aktualnie wykonywaną komendę rebase, w której znajdziesz sha1 oryginalnego commita:
$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
pick 4847406 US135756: add debugging to the file download code
e 65dfb6a US135756: write data and download from remote
(see more in file .git/rebase-merge/done)
...
W tym przypadku commit, który edytuję ma sha1 65dfb6a
. Wiedząc o tym, mogę sprawdzić zawartość tego commita w moim katalogu roboczym, używając formy git checkout
, która pobiera zarówno commit, jak i lokalizację pliku. Tutaj używam .
jako lokalizacji pliku, aby zastąpić całą kopię roboczą:
git checkout 65dfb6a .
Nie przegap kropka na końcu!
Spowoduje to sprawdzenie i zapisanie plików w takim stanie, w jakim były po edytowanym zatwierdzeniu, ale w stosunku do poprzedniego zatwierdzania, więc wszelkie zmiany, które już wprowadziłeś, nie będą częścią zatwierdzania.
Możesz albo przejść do przodu i zatwierdzić go w taki sposób, aby zakończyć podział, albo przejść do tyłu, usuwając niektóre części commita przed dokonaniem kolejnego tymczasowego commita.
Jeśli chcesz ponownie użyć oryginalnej wiadomości commit dla jednego lub więcej commitów, możesz użyj go bezpośrednio z plików roboczych rebase:
git commit --file .git/rebase-merge/message
Wreszcie, gdy już popełnisz wszystkie zmiany,
git rebase --continue
Będzie kontynuować i zakończyć operację rebase.
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-06-08 11:33:13
git rebase --interactive
może być użyty do podzielenia commita na mniejsze commity. W przypadku, gdy nie jest to możliwe, nie jest to możliwe.]}
W trybie interaktywnym możesz oznaczyć commity akcją "edytuj". Nie musi to jednak oznaczać, że
git rebase
spodziewa się, że wynik tej edycji będzie dokładnie jednym zatwierdzeniem. Rzeczywiście, możesz cofnąć zatwierdzenie lub dodać inne zmiany. To może być użyte do podzielenia commita na dwa:
Uruchom interaktywną rebase z
git rebase -i <commit>^
, Gdzie<commit>
jest zatwierdzeniem, które chcesz podzielić. W rzeczywistości każdy zakres commitów wystarczy, o ile zawiera ten commit.Zaznacz commit, który chcesz podzielić za pomocą akcji "edytuj".
Jeśli chodzi o edycję tego commita, wykonaj
git reset HEAD^
. Efekt polega na tym, że głowica jest przewijana o jeden, A Indeks podąża za nim. Jednak drzewo robocze pozostaje takie samo.Teraz dodaj zmiany do indeksu, który chcesz mieć w pierwszym commicie. Możesz użyć
git add
(ewentualnie interaktywnie) lub git gui (lub obu), aby to zrobić.Commit indeks now-current z dowolnym Komunikatem commit jest teraz odpowiedni.
Powtórz dwa ostatnie kroki, aż drzewo robocze będzie czyste.
Kontynuuj rebase za pomocą
git rebase --continue
.Jeśli nie jesteś absolutnie pewien, że wersje pośrednie są spójne (kompilują, zdać testsuite itp.) powinieneś użyć
git stash
, aby ukryć niezaangażowane zmiany po każdym commicie, przetestować i zmienić commit, jeśli poprawki są konieczne.
Możesz wykonać interaktywną rebase git rebase -i
. Strona Man ma dokładnie to, czego chcesz:
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-07-14 22:22:07
Zwróć uwagę, że istnieje również git reset --soft HEAD^
. Jest podobny do git reset
(domyślnie --mixed
), ale zachowuje zawartość indeksu. Tak, że jeśli dodałeś / usunąłeś pliki, masz je już w indeksie.
Okazuje się bardzo przydatny w przypadku commitów giant.
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-11-27 15:23:41
Teraz w najnowszym TortoiseGit na Windows możesz to zrobić bardzo łatwo.
Otwórz okno rebase, skonfiguruj go i wykonaj następujące kroki.
- kliknij prawym przyciskiem myszy commit, który chcesz podzielić i wybierz "
Edit
" (wśród pick, squash, delete...). - Kliknij "
Start
", Aby rozpocząć rebasing. - gdy dotrze do commit to split, zaznacz przycisk"
Edit/Split
" i kliknij bezpośrednio na "Amend
". Okno zatwierdzania otwiera.
- usuń zaznaczenie plików, które chcesz umieścić w osobnym zatwierdzeniu.
- Edytuj komunikat o zatwierdzeniu, a następnie kliknij "
commit
". - dopóki nie będzie plików do zatwierdzenia, okno dialogowe zatwierdzania będzie się otwierać ponownie i ponownie. Gdy nie ma już pliku do zatwierdzenia, nadal zapyta cię, czy chcesz dodać jeszcze jeden commit.
Bardzo pomocny, dzięki TortoiseGit !
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-04-22 10:32:46
Myślę, że najlepszy sposób używam git rebase -i
. Stworzyłem film pokazujący kroki dzielenia commita: https://www.youtube.com/watch?v=3EzOz7e1ADI
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-07-25 11:47:20
Najprostszą rzeczą do zrobienia bez interaktywnego rebase jest (prawdopodobnie) utworzenie nowej gałęzi zaczynającej się od commita przed tą, którą chcesz podzielić, cherry-pick-n commit, reset, stash, commit przenieś plik, ponownie zastosuj stash i zatwierdź zmiany, a następnie albo połącz się z poprzednią gałęzią, albo cherry-pick commity, które nastąpiły. (Następnie zmień poprzednią nazwę gałęzi na bieżącą głowicę.) (Prawdopodobnie lepiej postępować zgodnie z radami MBOs i zrobić interaktywną rebase.)
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
2010-01-22 17:04:50
Jeśli masz to:
A - B <- mybranch
Gdzie popełniłeś jakąś treść w commit B:
/modules/a/file1
/modules/a/file2
/modules/b/file3
/modules/b/file4
Ale chcesz podzielić B na C-D i uzyskać taki wynik:
A - C - D <-mybranch
Możesz podzielić zawartość w ten sposób na przykład (zawartość z różnych katalogów w różnych zatwierdzeniach)...
Zresetuj gałąź z powrotem do commita przed rozdzieleniem:
git checkout mybranch
git reset --hard A
Utwórz pierwszy commit (C):
git checkout B /modules/a
git add -u
git commit -m "content of /modules/a"
Utwórz drugi commit (D):
git checkout B /modules/b
git add -u
git commit -m "content of /modules/b"
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-02-08 17:44:48