git reset
przede wszystkim o przeniesienie HEAD
, i ogólnie oddział ref .
Pytanie: co z drzewem roboczym i indeksem?
W przypadku korzystania z --soft
, przenosi HEAD
, najczęściej aktualizuje referencję gałęzi i tylkoHEAD
.
To różni się od commit --amend
:
- nie tworzy nowego zatwierdzenia.
- może faktycznie przenieść HEAD do dowolnego zatwierdzenia (tak jak
commit --amend
tylko o nie przenoszeniu HEAD, jednocześnie pozwalając na ponowne wykonanie bieżącego zatwierdzenia)
Właśnie znalazłem ten przykład połączenia:
- klasyczne połączenie
- scalenie poddrzewa
wszystko w jeden (ośmiornica, ponieważ jest więcej niż dwie połączone gałęzie) zatwierdzić scalić.
Tomas „wereHamster” Carnecky wyjaśnia w swoim artykule „Scalanie ośmiornic poddrzewa” :
- Strategii scalania poddrzewa można użyć, jeśli chcesz scalić jeden projekt z podkatalogiem innego projektu, a następnie zachować aktualność podprojektu. Jest to alternatywa dla podmodułów git.
- Strategii łączenia ośmiornicy można użyć do scalenia trzech lub więcej gałęzi. Normalna strategia może łączyć tylko dwie gałęzie, a jeśli spróbujesz scalić więcej niż to, git automatycznie wróci do strategii ośmiornicy.
Problem w tym, że możesz wybrać tylko jedną strategię. Chciałem jednak połączyć te dwa elementy, aby uzyskać czystą historię, w której całe repozytorium jest atomowo aktualizowane do nowej wersji.
Mam superprojekt, nazwijmy go projectA
, i podprojekt projectB
, który połączyłem w podkatalogu projectA
.
(to jest część scalania poddrzewa)
Utrzymuję też kilka lokalnych zmian.
ProjectA
jest regularnie aktualizowany, projectB
ma nową wersję co kilka dni lub tygodni i zwykle zależy od konkretnej wersji projectA
.
Decydując się na aktualizację obu projektów, po prostu nie wyciągam z nich, projectA
a projectB
to spowodowałoby utworzenie dwóch zatwierdzeń dla czegoś, co powinno być atomową aktualizacją całego projektu .
Zamiast tworzyć jeden scalającej który łączy projectA
, projectB
a moim lokalnym zobowiązuje .
Problem polega na tym, że jest to scalanie ośmiornic (trzy głowy), ale projectB
musi zostać połączone ze strategią poddrzewa . Więc oto co robię:
# Merge projectA with the default strategy:
git merge projectA/master
# Merge projectB with the subtree strategy:
git merge -s subtree projectB/master
Tutaj autor użył a reset --hard
, a następnie, read-tree
aby przywrócić to, co zrobiły pierwsze dwa scalenia w drzewie roboczym i indeksie, ale to reset --soft
może pomóc:
Jak powtórzyć te dwa scalenia , które zadziałały, tj. Moje drzewo robocze i indeks są dobrze, ale bez konieczności nagrywania tych dwóch zatwierdzeń?
# Move the HEAD, and just the HEAD, two commits back!
git reset --soft HEAD@{2}
Teraz możemy wznowić rozwiązanie Tomasza:
# Pretend that we just did an octopus merge with three heads:
echo $(git rev-parse projectA/master) > .git/MERGE_HEAD
echo $(git rev-parse projectB/master) >> .git/MERGE_HEAD
# And finally do the commit:
git commit
Tak więc za każdym razem:
- jesteś zadowolony z tego, z czym skończysz (pod względem drzewa roboczego i indeksu)
- jesteś nie zadowolony z wszystkich zatwierdzeń, które miały ty się tam dostać:
git reset --soft
jest odpowiedzią.
git reset --soft
: stackoverflow.com/questions/6869705/ ...Przykład użycia - połącz serię lokalnych zatwierdzeń
„Ups. Te trzy zatwierdzenia mogą być tylko jednym”.
Więc cofnij ostatnie 3 (lub cokolwiek) zatwierdzenia (bez wpływu na indeks ani katalog roboczy). Następnie zatwierdź wszystkie zmiany jako jedną.
Na przykład
Teraz wszystkie zmiany są zachowane i gotowe do zatwierdzenia jako jedna.
Krótkie odpowiedzi na Twoje pytania
Czy te dwa polecenia są rzeczywiście takie same (
reset --soft
vscommit --amend
)?Czy jest jakiś powód, aby używać jednego lub drugiego w praktyce?
commit --amend
aby dodać / rm pliki z ostatniego zatwierdzenia lub zmienić jego komunikat.reset --soft <commit>
aby połączyć kilka kolejnych zatwierdzeń w nowe.A co ważniejsze, czy
reset --soft
oprócz zmiany zatwierdzenia są jakieś inne zastosowania ?źródło
reset --soft
oprócz zmiany zatwierdzenia - Nie”git reset
) są dobre, gdy (a) chcesz przepisać historię, (b) nie przejmujesz się starymi zatwierdzeniami (dzięki czemu możesz uniknąć kłopotów związanych z interaktywną rebase) i (c) mieć więcej niż jedno zobowiązanie do zmiany (w przeciwnym raziecommit --amend
jest prostsze).Używam go do poprawiania czegoś więcej niż tylko ostatniego zatwierdzenia.
Powiedzmy, że popełniłem błąd w zatwierdzeniu A, a następnie zatwierdziłem B. Teraz mogę tylko poprawić B. Więc robię
git reset --soft HEAD^^
, poprawiam i ponownie zatwierdzam A, a następnie ponownie zatwierdzam B.Oczywiście nie jest to zbyt wygodne w przypadku dużych zatwierdzeń… ale i tak nie powinieneś robić dużych zatwierdzeń ;-)
źródło
git commit --fixup HEAD^^
git rebase --autosquash HEAD~X
działa też dobrze.git rebase --interactive HEAD^^
gdzie wybierasz edycję zarówno zatwierdzeń A i B. W ten sposób zachowuje się komunikaty zmian A i B, w razie potrzeby nadal możesz je modyfikować.git reset A
, należy dodać zmiangit commit --amend
,git cherry-pick <B-commit-hash>
.Innym potencjalnym zastosowaniem jest alternatywa dla przechowywania (co niektórym się nie podoba, np. Https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/ ).
Na przykład, jeśli pracuję nad gałęzią i muszę pilnie naprawić coś na master, mogę po prostu zrobić:
następnie mistrz kasy i napraw. Kiedy skończę, wracam do swojego oddziału i robię
kontynuować pracę od miejsca, w którym skończyłem.
źródło
--soft
jest tutaj właściwie niepotrzebna, chyba że naprawdę zależy ci na natychmiastowym przygotowaniu zmian. Teraz po prostu używam,git reset HEAD~
kiedy to robię. Jeśli mam jakieś zmiany w fazie, gdy muszę zmienić gałęzie i chcę to tak zachować, to robięgit commit -m "staged changes"
, agit commit -am "unstaged changes"
potem późniejgit reset HEAD~
,git reset --soft HEAD~
aby całkowicie przywrócić stan roboczy. Chociaż, szczerze mówiąc, teraz robię obie te rzeczy o wiele rzadziejgit-worktree
:)Jednym praktycznym zastosowaniem jest to, że jeśli już zdecydowałeś się na lokalne repozytorium (np. Git commit -m), możesz cofnąć to ostatnie zatwierdzenie wykonując git reset --soft HEAD ~ 1
Również dla twojej wiedzy, jeśli już przygotowałeś swoje zmiany (np. Za pomocą git add.), Możesz odwrócić staging, wykonując reset git - mieszany HEAD lub często również po prostu użyłem
git reset
na koniec git reset --hard usuwa wszystko, łącznie z lokalnymi zmianami. Nagłówek ~ po nagłówku informuje, do ilu zatwierdzeń przejść od góry.
źródło
git reset --soft HEAD ~1
daje mifatal: Cannot do soft reset with paths.
, myślę, że musimy usunąć spację po HEAD, aby byłogit reset --soft HEAD~1
Możesz użyć,
git reset --soft
aby zmienić wersję, którą chcesz mieć jako nadrzędną dla zmian wprowadzonych w indeksie i drzewie roboczym. Przypadki, w których jest to przydatne, są rzadkie. Czasami możesz zdecydować, że zmiany, które wprowadziłeś w swoim drzewie roboczym, powinny dotyczyć innej gałęzi. Możesz też użyć tego jako prostego sposobu na zwinięcie kilku zatwierdzeń w jedno (podobnie do squash / fold).Zobacz odpowiedź VonC, aby uzyskać praktyczny przykład: Zgniatać pierwsze dwa zatwierdzenia w Git?
źródło
git reset --soft anotherBranch
i zatwierdzam tam? Ale tak naprawdę nie zmieniasz gałęzi ckeckout, więc czy zdecydujesz się przejść do Branch czy do innego Branch ?Jednym z możliwych zastosowań byłoby kontynuowanie pracy na innym komputerze. To działałoby tak:
Kup nowy oddział z nazwą podobną do skrytki,
Podnieś swoją gałąź skrytki
Przełącz się na inną maszynę.
Zdejmij zarówno swój zapas, jak i istniejące gałęzie,
Powinieneś być teraz w swoim istniejącym oddziale. Wklej zmiany z gałęzi skrytki,
Miękki reset istniejącej gałęzi do 1 przed połączeniem,
Usuń swoją gałąź skrytki,
Usuń także swoją gałąź skrytki od początku,
Kontynuuj pracę ze zmianami tak, jakbyś je normalnie schował.
Myślę, że w przyszłości GitHub i spółka. powinien oferować tę funkcję „zdalnego przechowywania” w mniejszej liczbie kroków.
źródło
Świetnym powodem użycia „
git reset --soft <sha1>
” jest ruchHEAD
do samego repozytorium.Jeśli spróbujesz użyć opcji
--mixed
lub--hard
, pojawi się błąd, ponieważ próbujesz zmodyfikować i robocze drzewo i / lub indeks, które nie istnieją.Uwaga: musisz to zrobić bezpośrednio z samego repozytorium.
Uwaga: Musisz upewnić się, że gałąź, którą chcesz zresetować w czystym repozytorium, jest gałęzią aktywną. Jeśli nie, postępuj zgodnie z odpowiedzią VonC, jak zaktualizować aktywną gałąź w gołym repozytorium, gdy masz bezpośredni dostęp do repozytorium.
źródło
SourceTree to GUI git, które ma całkiem wygodny interfejs do umieszczania tylko tych bitów, które chcesz. Nie ma niczego podobnego do poprawiania poprawnej wersji.
git reset --soft HEAD~1
Jest więc znacznie bardziej przydatne niżcommit --amend
w tym scenariuszu. Mogę cofnąć zatwierdzenie, przenieść wszystkie zmiany z powrotem do obszaru przejściowego i wznowić dostosowywanie etapowych bitów za pomocą SourceTree.Naprawdę wydaje mi się, że
commit --amend
jest to bardziej zbędne polecenie z tych dwóch, ale git to git i nie stroni od podobnych poleceń, które robią nieco inne rzeczy.źródło
Chociaż bardzo podobają mi się odpowiedzi w tym wątku, używam
git reset --soft
nieco innego, ale bardzo praktycznego scenariusza.Używam IDE do programowania, które ma dobre narzędzie porównywania do pokazywania zmian (wystawionych i niestacjonarnych) po moim ostatnim zatwierdzeniu. Obecnie większość moich zadań obejmuje wiele zatwierdzeń. Na przykład, powiedzmy, że wykonuję 5 zatwierdzeń, aby wykonać określone zadanie. Używam narzędzia porównywania w IDE podczas każdego zatwierdzenia przyrostowego od 1-5, aby przyjrzeć się moim zmianom od ostatniego zatwierdzenia. Uważam, że jest to bardzo pomocny sposób przeglądania zmian przed ich zatwierdzeniem.
Ale pod koniec mojego zadania, gdy chcę zobaczyć wszystkie moje zmiany razem (przed pierwszym zatwierdzeniem), aby dokonać przeglądu własnego kodu przed wykonaniem żądania ściągnięcia, zobaczyłem tylko zmiany z mojego poprzedniego zatwierdzenia (po zatwierdzeniu 4) i nie zmienia się ze wszystkich zatwierdzeń mojego obecnego zadania.
Więc używam,
git reset --soft HEAD~4
aby cofnąć się o 4 zatwierdzenia. To pozwala mi zobaczyć wszystkie zmiany razem. Kiedy jestem pewny swoich zmian, mogę to zrobićgit reset HEAD@{1}
i pewnie przenieść to na odległość.źródło
git add --patch
igit commit
wielokrotnie, aby zbudować serię zatwierdzeń, którą skonstruowałbyś, gdybyś wiedział, co robisz przez cały czas. Twoje pierwsze zatwierdzenia są jak notatki na twoim biurku lub pierwszy szkic notatki, służą do organizowania twojego myślenia, a nie do publikacji.git reset @{1}
przywracać pierwszą wersję roboczą serii, możesz zamiast tego utworzyć serię do publikacji zgit add -p
igit commit
.Innym przypadkiem użycia jest sytuacja, gdy chcesz zastąpić inną gałąź swoją w żądaniu ściągnięcia, na przykład powiedzmy, że masz oprogramowanie z funkcjami A, B, C.
Rozwijasz się z następną wersją i:
Usunięta funkcja B
Dodano funkcję D
W trakcie opracuj właśnie dodane poprawki dla funkcji B.
Możesz scalić program develop w next, ale czasami może to być kłopotliwe, ale możesz także użyć
git reset --soft origin/develop
i utworzyć zatwierdzenie ze swoimi zmianami, a gałąź można scalić bez konfliktów i zachować zmiany.Okazuje się, że
git reset --soft
to poręczna komenda. Osobiście używam go często do zgniatania zatwierdzeń, które nie mają „ukończonej pracy”, jak „WIP”, więc kiedy otwieram żądanie ściągnięcia, wszystkie moje zatwierdzenia są zrozumiałe.źródło