Jak zmiażdżyć wszystkie commity git w jeden?
Jak ściągnąć całe repozytorium do pierwszego commita?
Mogę przełączyć się na pierwszy commit, ale zostawi mi to 2 commity. Czy istnieje sposób, aby odwołać się do commita przed pierwszym?
15 answers
Być może najprostszym sposobem jest utworzenie nowego repozytorium z aktualnym stanem kopii roboczej. Jeśli chcesz zachować wszystkie komunikaty zatwierdzające, możesz najpierw wykonać git log > original.log
, a następnie edytować je dla początkowej wiadomości zatwierdzającej w nowym repozytorium:
rm -rf .git
git init
git add .
git commit
Lub
git log > original.log
# edit original.log as desired
rm -rf .git
git init
git add .
git commit -F original.log
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-11-01 14:23:33
W najnowszych wersjach Gita, możesz użyć git rebase --root -i
.
Dla każdego commita z wyjątkiem pierwszego, zmień pick
na squash
.
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-12-19 04:46:15
Update
Stworzyłem pseudonim git squash-all
.
przykładowe użycie: git squash-all "a brand new start"
.
[alias]
squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f"
Caveat: pamiętaj, aby dodać komentarz, w przeciwnym razie zostanie użyty domyślny komunikat commit "a new start".
Lub możesz utworzyć alias za pomocą następującego polecenia:
git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f'
One Liner
git reset $(git commit-tree HEAD^{tree} -m "A new start")
Uwaga : tutaj "A new start
" jest tylko przykładem, możesz używać własnego języka.
TL;DR
No need to squash, użyj git commit-tree
, aby utworzyć commit sierocy i przejść z nim.
Wyjaśnij
-
Utwórz pojedynczy commit poprzez
git commit-tree
Co
git commit-tree HEAD^{tree} -m "A new start"
robi to:Tworzy nowy obiekt zatwierdzania na podstawie dostarczonego obiektu drzewa i emituje nowy identyfikator obiektu commit na standardowym wyjściu. Komunikat dziennika jest odczyt ze standardowego wejścia, chyba że podano opcje-m lub-F.
Wyrażenie
HEAD^{tree}
oznacza obiekt drzewa odpowiadającyHEAD
, czyli końcówkę twojego obecny oddział. zobacz Tree-Objects i Commit-Objects. -
Zresetuj bieżącą gałąź do nowego commita
Następnie
git reset
wystarczy zresetować bieżącą gałąź do nowo utworzonej Zatwierdź obiekt.
W ten sposób nic w przestrzeni roboczej nie jest dotykane, ani nie ma potrzeba rebase/squasha, co sprawia, że jest naprawdę szybki. Potrzebny czas nie ma znaczenia dla rozmiaru repozytorium czy głębi historii.
Wariant: Nowy Repo od a Szablon Projektu
Jest to przydatne do utworzenia "initial commit" w nowym projekcie przy użyciu innego repozytorium jako szablonu/archetype/seed/skeleton. Na przykład:
cd my-new-project
git init
git fetch --depth=1 -n https://github.com/toolbear/panda.git
git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit")
Pozwala to uniknąć dodawania repo szablonu jako zdalnego (origin
lub innego) i zwija historię repo szablonu do początkowego zatwierdzenia.
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-17 13:35:33
Jeśli wszystko, co chcesz zrobić, to ściągnąć wszystkie commity do głównego commita, wtedy while
git rebase --interactive --root
Może działać, jest to niepraktyczne dla dużej liczby commitów (na przykład setek commitów), ponieważ operacja rebase prawdopodobnie będzie działać bardzo powoli, aby wygenerować interaktywną listę commitów edytora rebase, jak również uruchomić samą rebase.
Oto dwa szybsze i bardziej wydajne rozwiązania, gdy zgniatasz dużą liczbę commitów:
Alternatywne rozwiązanie #1: orphan branches
Możesz po prostu utworzyć nową, osieroconą gałąź na końcu (tj. najnowszym commicie) bieżącej gałęzi. Ta osierocona gałąź tworzy początkowy commit root z całkowicie nowego i oddzielnego drzewa historii commitów, co jest równoznaczne z zmiażdżeniem wszystkich commitów:
git checkout --orphan new-master master
git commit -m "Enter commit message for your new initial commit"
# Overwrite the old master branch reference with the new one
git branch -M new-master master
Dokumentacja:
Alternatywne rozwiązanie # 2: soft reset
Innym skutecznym rozwiązaniem jest aby po prostu użyć resetu mieszanego lub miękkiego do commita głównego <root>
:
git branch beforeReset
git reset --soft <root>
git commit --amend
# Verify that the new amended root is no different
# from the previous branch state
git diff beforeReset
Dokumentacja:
echo "message" | git commit-tree HEAD^{tree}
Spowoduje utworzenie osieroconego commita z drzewem głowy i wyświetli jego nazwę (SHA - 1) na standardowym wyjściu. Więc zresetuj swoją gałąź.
git reset SHA-1
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-07-23 15:04:21
Najprostszym sposobem jest użycie polecenia 'plumbing' update-ref
do usunięcia bieżącej gałęzi.
Nie możesz użyć git branch -D
, ponieważ posiada zawór bezpieczeństwa, który zatrzymuje usuwanie bieżącej gałęzi.
Spowoduje to powrót do stanu "początkowy commit", w którym możesz zacząć od nowego początkowego commita.
git update-ref -d refs/heads/master
git commit -m "New initial commit"
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-11-02 13:17:06
Oto jak skończyłem to robić, na wypadek, gdyby to działało dla kogoś innego:
Pamiętaj, że robienie takich rzeczy zawsze wiąże się z ryzykiem i nigdy nie jest złym pomysłem stworzenie gałęzi save przed uruchomieniem.
Zacznij od zalogowania
git log --oneline
Scroll to first commit, copy SHA
git reset --soft <#sha#>
Zastąp <#sha#>
w / SHA skopiowane z dziennika
git status
Upewnij się, że wszystko jest zielone, w przeciwnym razie uruchom git add -A
git commit --amend
Zmień wszystkie bieżące zmiany na bieżące pierwsze commit
Teraz naciśnij tę gałąź, a ona nadpisze to, co tam jest.
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
2015-11-05 16:04:50
Czytałem coś o użyciu przeszczepów, ale nigdy nie badałem tego zbyt wiele.
W każdym razie, możesz ręcznie zmiażdżyć ostatnie 2 commity czymś takim:
git reset HEAD~1
git add -A
git commit --amend
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-11-01 10:27:43
Najpierw połącz wszystkie commity w jeden commit używając git rebase --interactive
. Teraz zostały Ci dwa commity do squasha. Aby to zrobić, przeczytaj dowolny z
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-23 12:26:27
Do squasha za pomocą przeszczepów
Dodaj plik .git/info/grafts
, umieść tam hash commit, który chcesz stać się Twoim rootem
git log
rozpocznie się od tego commita
To make it 'real' run git filter-branch
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-05 19:12:11
"alternatywne rozwiązanie #1: orphan branches" mi pomaga.
" Git rebase --interactive --root " utknął w konflikcie plików gitignored.
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-26 13:17:19
Ta odpowiedź poprawia się na kilka powyższych (prosimy o głosowanie), zakładając, że oprócz utworzenia jednego commita (no-parents no-history), ty również chcesz zachować wszystkie dane commita tego commita:
- Autor (imię i e-mail)
- Data autora
- Commiter (nazwa i e-mail)
- Data zobowiązania
- commit log message
Oczywiście commit-SHA nowego / pojedynczego commita zmieni się, ponieważ reprezentuje nowy (Nie-)historia, staje się parentless / root-commit.
Można to zrobić poprzez odczytanie git log
i ustawienie niektórych zmiennych dla git commit-tree
. Zakładając, że chcesz utworzyć pojedynczy commit z master
w nowej gałęzi one-commit
, zachowując powyższe dane commit:
git checkout -b one-commit master ## create new branch to reset
git reset --hard \
$(eval "$(git log master -n1 --format='\
COMMIT_MESSAGE="%B" \
GIT_AUTHOR_NAME="%an" \
GIT_AUTHOR_EMAIL="%ae" \
GIT_AUTHOR_DATE="%ad" \
GIT_COMMITTER_NAME="%cn" \
GIT_COMMITTER_EMAIL="%ce" \
GIT_COMMITTER_DATE="%cd"')" 'git commit-tree master^{tree} <<COMMITMESSAGE
$COMMIT_MESSAGE
COMMITMESSAGE
')
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-01-28 17:27:50
Zwykle robię to tak:
-
Upewnij się, że wszystko jest zatwierdzone i zapisz najnowszy identyfikator zatwierdzenia na wypadek, gdyby coś poszło nie tak, lub utwórz oddzielną gałąź jako kopię zapasową
Uruchom
git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD`
, aby zresetować głowę do pierwszego commita, ale pozostaw indeks bez zmian. Wszystkie zmiany od pierwszego commita będą teraz gotowe do zatwierdzenia.Uruchom
git commit --amend -m "initial commit"
, Aby zmienić commit do pierwszego commita I zmienić komunikat commit, lub jeśli chcesz zachowaj istniejący komunikat commit, możesz uruchomićgit commit --amend --no-edit
-
Run
git push -f
to force push your changes
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-18 13:13:28
Tworzenie kopii zapasowej
git branch backup
Reset do podanego commita
git reset --soft <root>
Dodaj wszystkie pliki do stagingu
git add .
Zatwierdź bez aktualizacji wiadomości
git commit --amend --no-edit
Push new branch with squashed commits to repo
git push -f
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-07-19 14:12:55
W jednej linijce 6 słów
git checkout --orphan new_root_branch && git commit
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-08-15 21:57:00