Zaawansowany przewodnik po Git: skrytka Git, resetowanie, zmiana bazy i więcej
Opublikowany: 2022-03-11Każdy programista powinien dobrze rozumieć kontrolę wersji, a Git stał się de facto standardem kontroli wersji w tworzeniu oprogramowania.
Często jednak programiści uczą się tylko kilku prostych poleceń i pomijają moc historii Git i inne rzeczy, które Git może zrobić, aby zwiększyć wydajność. Na przykład zarządzanie wydaniami jest bardzo łatwe dzięki Git przy użyciu git tag
.
Wziąłem zaawansowany kurs Git online (z GitHub) i zacząłem prowadzić klasę Git dla początkujących w połączeniu z Github. Kiedy zauważyłem, że nie ma zbyt wielu artykułów technicznych na temat moich ulubionych funkcji Git, skorzystałem z okazji, aby podzielić się nimi z innymi programistami. W tym poście dowiesz się, jak wykorzystać następujące zaawansowane funkcje Git:
-
git stash
, który tworzy tymczasowy, lokalny zapis twojego kodu -
git reset
, który pozwala uporządkować kod przed wykonaniem zatwierdzenia -
git bisect
, funkcja, która pozwala wyłapać złe zmiany -
git squash
, który pozwala na łączenie Twoich commitów -
git rebase
, który pozwala na nanoszenie zmian z jednej gałęzi na drugą
Skrytka Gita
Skrytka Git umożliwia zapisanie kodu bez dokonywania zmian. Jak to jest przydatne? Wyobraź sobie następujący scenariusz:
Wykonałeś już trzy schludne i uporządkowane zatwierdzenia, ale masz też trochę niezatwierdzonego kodu, który jest dość niechlujny; nie będziesz chciał go zatwierdzić bez uprzedniego usunięcia kodu debugowania. Wtedy, z jakiegoś powodu, nagle musisz zająć się innym zadaniem i musisz zmienić gałęzie. Może się to często zdarzyć, jeśli jesteś w swoim main
oddziale i zapomniałeś utworzyć nową gałąź dla swojej funkcji. W tej chwili Twój kod wygląda tak:
$ git status On branch my-feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss no changes added to commit (use "git add" and/or "git commit -a")
$ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; }
Po uruchomieniu git stash
, niezatwierdzony kod znika bez zatwierdzenia. Przechowywanie jest jak zapisywanie tymczasowego zobowiązania lokalnego w Twoim oddziale. Nie jest możliwe wypchnięcie skrytki do zdalnego repozytorium, więc skrytka jest tylko do użytku osobistego.
$ git stash Saved working directory and index state WIP on my-feature: 49ee696 Change text color
Twoja gałąź wygląda teraz tak, jak przed ostatnim zatwierdzeniem. Teraz możesz bezpiecznie zmieniać gałęzie bez utraty kodu lub bałaganu. Kiedy przełączysz się z powrotem do swojego brancha i uruchomisz git stash list
, zobaczysz listę skrytek, która wygląda mniej więcej tak:
$ git stash list stash@{0}: WIP on my-feature: 49ee696 Change text color
Możesz łatwo ponownie zastosować ukrytą zawartość, uruchamiając git stash apply
. Możesz również zastosować konkretną skrytkę (jeśli składowałeś więcej niż jeden raz), uruchamiając git stash apply stash@{1}
(liczba „1” oznacza przedostatnią skrytkę). Oto przykład przechowywania więcej niż jednego zatwierdzenia i zastosowania innego schowka:
$ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; } $ git stash Saved working directory and index state WIP on my-feature: 49ee696 Change text color $ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..b63c664 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; } $ git stash Saved working directory and index state WIP on my-feature: 49ee696 Change text color
$ git stash list stash@{0}: WIP on my-feature: 49ee696 Change text color stash@{1}: WIP on my-feature: 49ee696 Change text color stash@{2}: WIP on my-feature: 49ee696 Change text color $ git stash apply stash@{2} On branch my-feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss no changes added to commit (use "git add" and/or "git commit -a")
git stash apply stash@{2}
zastosował najstarszy ukryty kod, kiedy zmieniliśmy kolor tekstu na czerwony.
$ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: #333; + color: red; background-color: #f00; }
Jeśli zdecydujesz się nie zatwierdzać swojej pracy po przywróceniu skrytki, możesz uruchomić git checkout .
, który resetuje cały niezatwierdzony kod.
Jako kolejny przykład użycia Git Stash: powiedzmy, że masz nowe pliki, z których jeden zawiera błąd. Pozostaw wszystkie pliki z wyjątkiem podejrzanego o błąd w przemieszczeniu (kod musi zostać przemieszczony, aby można go było przechowywać), a następnie możesz ukryć ten plik i rozwiązać problem. Jeśli ukryty plik nie był problemem, możesz go przywrócić.
$ git status On branch my-feature Untracked files: (use "git add <file>..." to include in what will be committed) css/colors.scss nothing added to commit but untracked files present (use "git add" to track)
$ git add css/colors.scss $ git stash Saved working directory and index state WIP on my-feature: 0d8deef delete colors $ git status On branch my-feature nothing to commit, working tree clean $ git stash apply stash@{0} On branch my-feature Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: css/colors.scss
Możesz również przenieść swoje ukryte zatwierdzenia do nowej gałęzi funkcji lub gałęzi debugowania za pomocą git stash branch
:
$ git status On branch my-feature Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss no changes added to commit (use "git add" and/or "git commit -a") $ git stash Saved working directory and index state WIP on my-feature: 66f3f3b Add colors file $ git stash branch debugging-branch M css/common.scss Switched to a new branch 'debugging-branch' Unstaged changes after reset: M css/common.scss On branch debugging-branch Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss Dropped refs/stash@{0} (d140624f60d8deef7bceb0d11fc80ed4fd47e0a1)
Zwróć uwagę, że po zastosowaniu skrytki skrytka nie jest usuwana. Możesz usunąć skrytki pojedynczo za pomocą git drop
lub usunąć wszystkie skrytki za pomocą git stash clear
:
$ git stash list stash@{0}: WIP on my-feature: 66f3f3b Add colors file stash@{1}: WIP on my-feature: 0d8deef delete colors stash@{2}: WIP on my-feature: 49ee696 Change text color $ git stash drop stash@{2} Dropped stash@{2} (8ed6d2ce101aa2e28c8ccdc94cb12df8e5c468d6) $ git stash list stash@{0}: WIP on my-feature: 66f3f3b Add colors file stash@{1}: WIP on my-feature: 0d8deef delete colors $ git stash clear $ git stash list $
Resetowanie Gita
Jeśli znajdziesz się w sytuacji, w której przypadkowo popełniłeś jakiś niechlujny kod, możesz wykonać „miękki” reset. Oznacza to, że kod wygląda tak, jakby nie został jeszcze zatwierdzony. Następnie możesz uporządkować swój kod w swoim IDE przed wykonaniem czystszego zatwierdzenia. Aby to zrobić, możesz uruchomić git reset --soft HEAD~1
. Spowoduje to zresetowanie ostatniego zatwierdzenia. Możesz cofnąć więcej niż jedno zatwierdzenie, zmieniając numer po ~
np. git reset --soft HEAD~2
.
$ git reset --soft HEAD~1 $ git status On branch debugging-branch Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: css/common.scss Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: css/common.scss
$ git diff diff --git a/css/common.scss b/css/common.scss index 2090cc4..90fd457 100644 --- a/css/common.scss +++ b/css/common.scss @@ -13,6 +13,6 @@ body { font-family: "Proxima Nova", Arial, sans-serif; font-size: 13px; - color: $grey; + color: red; background-color: #f00; }
Resetowanie Git jest nieco bardziej zagmatwane, zwłaszcza podczas uczenia nowych użytkowników Git. Miękki reset powinien być zarezerwowany na prawdziwy błąd, podczas gdy skrytka może służyć do wymiany kodu.
Możesz także wykonać twardy reset ( git reset --hard HEAD~1
). Ten rodzaj resetowania zasadniczo usuwa ostatnie zatwierdzenie. Powinieneś być bardzo ostrożny podczas wykonywania twardych resetów, zwłaszcza jeśli wypchniesz swoją gałąź, ponieważ nie ma możliwości przywrócenia zatwierdzenia.
Git na pół
Moim ulubionym narzędziem Git jest git bisect
. Potrzebowałem tego tylko kilka razy, ale kiedy to zrobiłem, było to nieocenione! Używałem go głównie w dużych bazach kodu, w których wystąpił problem, dla którego nikt nie znalazł przyczyny, nawet po energicznym debugowaniu.
git bisect
zasadniczo wykonuje wyszukiwanie binarne między dwoma podanymi zatwierdzeniami, a następnie przedstawia szczegóły konkretnego zatwierdzenia. Najpierw musisz dać Gitowi dobre zatwierdzenie, w którym wiesz, że twoja funkcjonalność działała, i zły zatwierdzenie. Zwróć uwagę, że dopóki masz jedno dobre i jedno złe zatwierdzenie, mogą one być od siebie oddalone o lata (chociaż im dalej w czasie się cofasz, tym trudniej jest to zrobić!).
Najbardziej zabawną rzeczą w git bisect
jest to, że zwykle nie wiesz, kto napisał zatwierdzenie z błędami, kiedy zaczynasz. Podekscytowanie odkryciem, gdzie wprowadzono błąd, niejednokrotnie spowodowało, że kilku współpracowników zebrało się wokół mojego komputera!
Aby rozpocząć, sprawdź gałąź z błędami i znajdź dobre zatwierdzenia. Będziesz musiał przejrzeć historię commitów i znaleźć hash, a następnie sprawdzić ten konkretny commit i przetestować swoją gałąź. Gdy znajdziesz dobre i złe miejsce do pracy, możesz uruchomić git bisect
.
W tym scenariuszu tekst na tej stronie internetowej, którą stworzyliśmy, jest czerwony (chociaż może korzystać z projektanta interfejsu użytkownika), ale nie wiemy, jak i kiedy stał się czerwony. To bardzo prosty przykład, w prawdziwym scenariuszu prawdopodobnie miałbyś znacznie mniej oczywisty problem, np. formularz nie jest przesyłany/działa.
Kiedy uruchamiamy git log
, możemy zobaczyć listę zatwierdzeń do wyboru.
$ git log commit a3cfe7f935c8ad2a2c371147b4e6dcd1a3479a22 (HEAD -> main) Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:52:57 2021 +0100 Update .gitignore file for .DS_Store commit 246e90977790967f54e878a8553332f48fae6edc Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:51:23 2021 +0100 Change styling of page commit d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:50:48 2021 +0100 Change text color commit 032a41136b6653fb9f7d81aef573aed0dac3dfe9 Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:42:57 2021 +0100 Change text color commit 246e90977790967f54e878a8553332f48fae6edc Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:41:23 2021 +0100 delete colors commit d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:50:48 2021 +0100 Change text color commit ce861e4c6989a118aade031020fd936bd28d535b Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:07:36 2021 +0100 ...
Jeśli otworzę stronę internetową z najnowszym hashem zatwierdzenia, tekst jest czerwony, więc wiem, że mam problem.
Teraz zaczynamy przecinanie i mówimy Gitowi, że mamy złe zatwierdzenie.
$ git bisect start $ git bisect bad 8d4615b9a963ef235c2a7eef9103d3b3544f4ee1
Teraz cofamy się w czasie, aby spróbować znaleźć zatwierdzenie, w którym tekst nie był czerwony. Tutaj próbuję sprawdzić mój pierwszy commit…
$ git checkout ce861e4c6989a118aade031020fd936bd28d535b Note: checking out 'ce861e4c6989a118aade031020fd936bd28d535b'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at ce861e4 Add CSS styles
…i odświeżenie strony…
Tekst nie jest już czerwony, więc jest to dobre zatwierdzenie! Im nowszy commit, czyli im bliżej złego commita, tym lepiej:
$ git checkout d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Previous HEAD position was ce861e4c6989a118aade031020fd936bd28d535b Add CSS styles HEAD is now at d647ac4 Change text color
Git powie ci teraz, ile zatwierdzeń musi przeszukać, zanim znajdzie właściwy. Liczba zatwierdzeń, które przejdzie Git, zależy od tego, ile zatwierdzeń znajduje się pomiędzy dobrym i złym zatwierdzeniem (im dłuższy czas, tym więcej razy Git musi wykonać iterację).
Teraz musisz ponownie przetestować swoją gałąź i sprawdzić, czy problem zniknął. Czasami może to być trochę kłopotliwe, jeśli regularnie aktualizujesz moduły, ponieważ może być konieczne ponowne zainstalowanie modułów węzłów w repozytorium frontonu. Jeśli nastąpiły aktualizacje bazy danych, być może będziesz musiał je również zaktualizować.
git bisect
automatycznie sprawdza zatwierdzenie w środku twoich dobrych i złych zatwierdzeń. Tutaj jest szacowanie jednego kroku, aby znaleźć złe zatwierdzenie.
$ git bisect good 1cdbd113cad2f452290731e202d6a22a175af7f5 Bisecting: 1 revision left to test after this (roughly 1 step) [ce861e4c6989a118aade031020fd936bd28d535b] Add CSS styles $ git status HEAD detached at ce861e4 You are currently bisecting, started from branch '8d4615b'. (use "git bisect reset" to get back to the original branch)
Odśwież stronę i sprawdź, czy problem zniknął. Problem nadal istnieje, więc mówimy Gitowi, że to nadal jest złe zatwierdzenie. Tym razem nie ma potrzeby odwoływania się do skrótu zatwierdzenia, ponieważ Git użyje zatwierdzenia, które pobrałeś. Będziemy musieli powtarzać ten proces, dopóki Git nie wykona wszystkich możliwych kroków.
$ git bisect bad Bisecting: 0 revisions left to test after this (roughly 0 steps) [cbf1b9a1be984a9f61b79ae5f23b19f66d533537] Add second paragraph to page
Odśwież stronę, a nasz problem znowu zniknie, więc to jest dobre zatwierdzenie:

Na tym etapie Git znalazł pierwsze złe zatwierdzenie:
$ git bisect good ce861e4c6989a118aade031020fd936bd28d535b is the first bad commit commit ce861e4c6989a118aade031020fd936bd28d535b Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:52:57 2021 +0100 Add CSS styles :000000 100644 0000000000000000000000000000000000000000 092bfb9bdf74dd8cfd22e812151281ee9aa6f01a M css
Teraz możemy użyć git show
aby pokazać sam commit i zidentyfikować problem:
$ git show ce861e4c6989a118aade031020fd936bd28d535b commit ce861e4c6989a118aade031020fd936bd28d535b Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:52:57 2021 +0100 Add CSS styles diff --git a/css/base.scss b/css/base.scss index e69de29..26abf0f 100644 --- a/css/base.scss +++ b/css/base.scss @@ -1,7 +1,7 @@ body { background-color: $white; margin: 0px; line-height: 20px; - color: $grey; + color: red; }
Kiedy skończysz, możesz uruchomić git bisect reset
, aby zresetować gałąź do normalnego stanu roboczego.
Im bliżej siebie znajdują się zmiany, tym łatwiej Git będzie w stanie znaleźć problem, ale kazałem mu wykonać 10 kroków wcześniej i nadal łatwo znaleźć złe zatwierdzenie. Nie ma gwarancji, że zadziała, ale przez większość czasu znajdował dla mnie problem. Gratulacje, teraz jesteś archeologiem kodu!
Niszczenie swoich zobowiązań
Wcześniej pracowałem na pełny etat nad projektem open source dla globalnej organizacji i szybko nauczyłem się, jak ważne jest zmiażdżenie — lub połączenie — swoich zobowiązań. Myślę, że to świetny nawyk, aby się w to wrobić, nawet jeśli twój pracodawca tego nie wymaga. Jest to szczególnie ważne dla innych programistów, którzy będą musieli przeglądać i edytować funkcje, które zbudowałeś później.
Po co zgniatać swoje commity?
- Współtwórcy Twojego repozytorium mogą łatwiej czytać. Wyobraź sobie, że masz taką listę zmian:
- Implementuj suwak karuzeli
- Dodaj stylizację do karuzeli
- Dodaj przyciski do karuzeli
- Napraw dziwny problem w IE za pomocą karuzeli
- Dostosuj marginesy w karuzeli
Dużo łatwiej jest zmieścić je w jednym zatwierdzeniu, które mówi „Dodaj karuzelę do strony głównej”.
- Zachęca Cię do tego, aby Twoje komunikaty o zatwierdzeniu były zrozumiałe i trafne, jeśli za każdym razem, gdy wykonujesz żądanie ściągnięcia, musisz zmiażdżyć swoje zmiany w jednym. Ile razy widziałeś zatwierdzenie zatytułowane „WIP”, „poprawka błędu na stronie logowania” lub „naprawa literówka”? Ważne jest, aby mieć odpowiednie nazwy zatwierdzeń, np. „Poprawka błędu strony logowania #444 - napraw migotanie spowodowane brakiem funkcji $scope”.
Powodem, dla którego możesz nie chcieć zgniatać swoich zatwierdzeń, może być to, że pracujesz nad bardzo szczegółową i długą funkcją i chcesz zachować codzienną historię dla siebie na wypadek, gdyby później natkniesz się na błędy. Wtedy Twoja funkcja będzie łatwiejsza do debugowania. Jednak, gdy sprawdzasz swoją funkcję w swojej głównej gałęzi i masz pewność, że jest wolna od błędów, nadal ma sens zgniecenie.
W tym scenariuszu wykonałem pięć zatwierdzeń, ale wszystkie dotyczą jednej funkcji. Moje komunikaty o zatwierdzeniu są również zbyt blisko związane z oddzieleniem zasług — wszystkie moje zatwierdzenia dotyczą stylizacji strony pod kątem tej nowej funkcji:
$ git log commit a8fbb81d984a11adc3f72ce27dd0c39ad24403b7 (HEAD -> main) Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 11:16:10 2021 +0100 Import colors commit e2b3ddd5e8b2cb1e61f88350d8571df51d43bee6 Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 11:15:32 2021 +0100 Add new color commit d647ac489ad43b3c6eaea5aceb02b0a7d7e5cf8e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 10:50:48 2021 +0100 Change text color commit c005d9ceeefd4a8d4e553e825fa40aaafdac446e Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 09:59:57 2021 +0100 Add CSS styles commit 9e046b7df59cef07820cc90f694fabc666731bd2 Author: Ursula Clarke <[email protected]> Date: Tue Jan 11 09:56:28 2021 +0100 Add second paragraph to page commit 5aff973577d67393d914834e8af4c5d07248d628 Author: Ursula Clarke <[email protected]> Date: Mon Jan 10 16:04:22 2021 +0100 Add colors CSS file and edit background color
Możesz również użyć git merge --squash
, ale myślę, że bardziej przejrzyste jest użycie rebase
, ponieważ kiedy wybierzesz swoje zatwierdzenia, łatwiej jest zobaczyć opis zatwierdzenia. Jeśli uruchomisz git merge --squash
, musisz najpierw wykonać twardy reset swoich zatwierdzeń ( git reset --hard HEAD~1
) i łatwo jest pomylić się z dokładną liczbą zatwierdzeń, z którymi musisz to zrobić. Uważam, że git rebase
jest bardziej wizualny.
Zacznij od uruchomienia git rebase -i --root
, a domyślny edytor tekstu w wierszu poleceń otworzy się z listą zatwierdzeń:
pick eb1eb3c Update homepage pick 5aff973 Add colors CSS file and edit background color pick 9e046b7 Add second paragraph to page pick c005d9c Add CSS styles pick d647ac4 Change text color pick e2b3ddd Add new color pick a8fbb81 Import colors # Rebase a8fbb81 onto b862ff2 (7 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
Możesz po prostu chcieć zmiażdżyć kilka ostatnich zatwierdzeń, w takim przypadku możesz uruchomić git rebase -i HEAD~3
i zobaczyć ostatnie trzy zatwierdzenia:
pick eb1eb3c Update homepage pick 5aff973 Add colors CSS file and edit background color pick 9e046b7 Add second paragraph to page # Rebase b862ff2..9e046b7 onto b862ff2 (3 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
Teraz możemy wcisnąć wszystkie zatwierdzenia do pierwszego zatwierdzenia, jak pokazano poniżej.
pick eb1eb3c Update homepage squash 5aff973 Add colors CSS file and edit background color squash 9e046b7 Add second paragraph to page # Rebase b862ff2..9e046b7 onto b862ff2 (3 commands) # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # d, drop = remove commit # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
Gdy zapiszesz plik, Git otworzy wiadomość dotyczącą zatwierdzenia do edycji.
# This is a combination of 3 commits. # This is the 1st commit message: Update homepage # This is the commit message #2: Add colors CSS file and edit background color # This is the commit message #3: Add second paragraph to page # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Wed Jan 13 18:31:28 2021 +0100 # # interactive rebase in progress; onto b862ff2 # Last commands done (3 commands done): # squash 5aff973 Add colors CSS file and edit background color # squash 9e046b7 Add second paragraph to page # No commands remaining. # You are currently rebasing branch 'main' on 'b862ff2'. # # Changes to be committed: # new file: .gitignore # new file: css/base.css # new file: css/base.scss # new file: css/colors.css # new file: css/colors.css.map # new file: css/colors.scss # new file: css/common.css # new file: css/common.scss # new file: index.html #
Podczas gdy robimy zmianę bazy, możemy również edytować opis zatwierdzenia, aby był łatwiejszy do odczytania.
Implement new design for homepage. Add .gitignore file for Sass folder. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. #
Zapisz ten plik ponownie i gotowe! Kiedy ponownie spojrzymy na dziennik Git, zobaczymy, że jest tylko jedno czyste zatwierdzenie.
[detached HEAD 574ec7e] Implement new design for homepage. Add .gitignore file for Sass folder. Date: Wed Jan 13 18:31:28 2021 +0100 10 files changed, 215 insertions(+) create mode 100644 .gitignore create mode 100644 css/base.css create mode 100644 css/base.scss create mode 100644 css/colors.css create mode 100644 css/colors.css.map create mode 100644 css/colors.scss create mode 100644 css/common.css create mode 100644 css/common.scss create mode 100644 index.html create mode 100644 verylargefile.txt Successfully rebased and updated refs/heads/main. $ git log commit 574ec7e5d7d7a96427e049cad9806cdef724aedd (HEAD -> main) Author: Ursula Clarke <[email protected]> Date: Wed Jan 13 18:31:28 2021 +0100 Implement new design for homepage. Add .gitignore file for Sass folder.
Zmiana bazy Gita
Deweloperzy zwykle niechętnie korzystają z git rebase
, ponieważ wiedzą, że rebase może służyć do trwałego usuwania plików z bazy kodu.
Jak widzieliśmy powyżej, git rebase
może być używany do przechowywania kodu i porządkowania go, a także do usuwania – ale co, jeśli naprawdę chcesz trwale usunąć plik z historii?
Byłem kiedyś świadkiem scenariusza, w którym członek naszego zespołu programistów przypadkowo zapisał bardzo duży plik do bazy kodu. Był częścią znacznie większej gałęzi, więc duży plik został niezauważony podczas przeglądu kodu i został omyłkowo wpisany do głównej gałęzi. Stało się to problemem, gdy ktoś chciał ponownie sklonować repozytorium - pobranie zajęło bardzo dużo czasu! I oczywiście przedmiotowy plik był niepotrzebny. Nie byłoby problemu, gdyby plik był ostatnim zatwierdzeniem głównej gałęzi — w takim przypadku można po prostu uruchomić twardy reset ( git reset --hard HEAD~1
) i wymusić wypchnięcie gałęzi.
Podobnie, jeśli plik był jedyną zmianą w danym zatwierdzeniu, możesz po prostu usunąć całe zatwierdzenie, uruchamiając git reset --hard <commit-id>
. Jednak w naszym scenariuszu duży plik został zatwierdzony wraz z innym kodem, który chcieliśmy zachować w historii, jako zatwierdzenie od przedostatniej sekundy.
Po znalezieniu kłopotliwego zatwierdzenia, sprawdź go za pomocą git checkout
i skrótu zatwierdzenia:
$ git checkout ce861e4c6989a118aade031020fd936bd28d535b Note: checking out 'ce861e4c6989a118aade031020fd936bd28d535b'. You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b <new-branch-name> HEAD is now at ce861e4 Add CSS styles
Usuń plik lub edytuj kod, a kod (lub pliki), które chcesz zachować, pozostaw nienaruszony.
$ rm verylargefile.txt $ git status HEAD detached at ce861e4 Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) deleted: verylargefile.txt no changes added to commit (use "git add" and/or "git commit -a")
Upewnij się, że uruchomiłeś git add -A
, aby usunięty plik został umieszczony w poczekalni, a Git wiedział, że ma go usunąć. Teraz uruchom git commit --amend -v
, a Git poprosi Cię o edycję komunikatu zatwierdzenia.
Następnie uruchom git rebase --onto HEAD <commit-id> main
. W tym miejscu możesz natknąć się na konflikty scalania, co oznacza, że istnieje konflikt między nowym zatwierdzeniem a starym kodem. Git poprosi Cię o rozwiązanie konfliktu:
$ git add -A $ git status HEAD detached at ce861e4 Changes to be committed: (use "git reset HEAD <file>..." to unstage) deleted: verylargefile.txt $ git commit --amend -v [detached HEAD 7c9516a] Add CSS styles Date: Thu Jan 14 14:43:54 2021 +0100 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 css/common.css.map delete mode 100644 verylargefile.txt $ git status HEAD detached from ce861e4 nothing to commit, working tree clean $ git rebase --onto HEAD ce861e4 First, rewinding head to replay your work on top of it... Fast-forwarded HEAD to HEAD.
Jeśli otworzysz plik w edytorze tekstu, zobaczysz, że Git oznaczył dwie wersje pliku indeksu. Musisz po prostu usunąć jeden lub edytować, aby zachować zmiany, które Ci się podobają.
<p> Toptal was created by engineers. We are entrepreneurs, all passionate about working with top tech talent and exciting companies from all over the world. </p> <<<<<<< HEAD <p> Toptal connects the top 3% of freelance talent all over the world. </p> </main> </body> </html> ======= </main> </body> </html> >>>>>>> Add index file
Kod pomiędzy <<<<<<< HEAD
i linią znaków równości to jedna wersja, a kod pomiędzy znakami równości a >>>>>>> Add index file
to wersja z zatwierdzenia „Dodaj plik indeksu” . Widać więc, że jedna wersja ma dodatkowy akapit „Toptal łączy 3% najlepszych niezależnych talentów na całym świecie”, podczas gdy druga nie.
Zapisz edytowany plik i uruchom git add filename
, a następnie git rebase --continue
. Jeśli nie ma żadnych zmian, możesz również uruchomić git rebase --skip
. Zmiana bazy może zająć trochę czasu, jeśli między zatwierdzeniem „dużego pliku” a ostatnim zatwierdzeniem w głównym pliku było dużo zatwierdzeń.
Bądź cierpliwy, a jeśli jesteś w dużym zespole, zdobądź drugą opinię! Jeśli to możliwe, szczególnie ważne jest skonsultowanie się z osobami, które napisały zatwierdzenia, które łączysz.
Pamiętaj, że scalone zmiany dotyczą konkretnego zatwierdzenia w historii, a nie najnowszych zmian. Np. jeśli edytujesz zatwierdzenie od czasu, gdy tekst na Twojej stronie był Arial, a teraz jest to Verdana, nadal powinieneś zachować to zatwierdzenie z historią Arial jako krojem czcionki.
Zauważ też, że jeśli Git widzi spację lub znak końca linii, może to spowodować konflikt scalania, więc bądź ostrożny!
Więcej niż tylko zobowiązuj się i ciągnij
Git jest potężniejszy niż wielu programistów myśli. Jeśli zdarzy ci się przedstawiać nowicjusza, daj mu kilka wskazówek na temat tych bezcennych funkcji. Zapewnia to wydajniejszy przepływ pracy.
Chcesz dowiedzieć się więcej o Git? Zajrzyj na stronę Toptal z poradami i praktykami Git.