Nie mam doświadczenia z kontrolą wersji i rozumiem, że „zatwierdzanie” to zasadniczo tworzenie kopii zapasowej podczas aktualizowania nowej „bieżącej” wersji tego, nad czym pracujesz.
Nie rozumiem, do czego służy inscenizacja z praktycznego punktu widzenia. Czy wystawianie czegoś, co istnieje tylko z nazwy, czy służy celowi? Kiedy się zgodzisz, i tak zrobisz wszystko, prawda?
Edycja: Myślę, że mogę mylić terminologię. Czy plik „przemieszczany” to to samo, co plik „śledzony”?
Odpowiedzi:
Kiedy zatwierdzasz, zatwierdza tylko zmiany w indeksie (pliki „przemieszczane”). Ma to wiele zastosowań, ale najbardziej oczywistym jest rozbicie zmian roboczych na mniejsze, samodzielne części. Być może naprawiłeś błąd podczas implementowania funkcji. Możesz
git add
po prostu ten plik (lubgit add -p
dodać tylko część pliku!), A następnie zatwierdzić tę poprawkę przed zatwierdzeniem wszystkiego innego. Jeśli używaszgit commit -a
, to po prostu wymuszaszadd
wszystko tuż przed zatwierdzeniem. Nie używaj,-a
jeśli chcesz skorzystać z plików przejściowych.Pliki przemieszczane można również traktować jako pośrednią kopię roboczą za pomocą
--cached
wielu poleceń. Na przykładgit diff --cached
pokaże ci, czym różni się etapHEAD
, abyś mógł zobaczyć, co zamierzasz zatwierdzić, bez mieszania innych zmian roboczych.źródło
git reset --hard
.git diff --staged
i sprawdź, które pliki zmieniłeś i gdzie, i zacznij wprowadzać inne zmiany.źródło
Jednym z praktycznych celów przemieszczania jest logiczna separacja zatwierdzeń plików.
Ponieważ pomost pozwala na kontynuowanie edycji plików / katalogu roboczego i dokonywanie zatwierdzeń w częściach, gdy myślisz, że wszystko jest gotowe, możesz użyć oddzielnych etapów dla logicznie niepowiązanych edycji.
Załóżmy, że masz 4 pliki
fileA.html
,fileB.html
,fileC.html
ifileD.html
. Wprowadzasz zmiany we wszystkich 4 plikach i jesteś gotowy do zatwierdzenia, ale zmiany wfileA.html
ifileB.html
są logicznie powiązane (na przykład ta sama nowa implementacja funkcji w obu plikach), podczas gdy zmiany wfileC.html
ifileD.html
są oddzielne i logicznie niezwiązane z poprzednimi plikami. Pierwsze pliki stage możnafileA.html
ifileB.html
i popełnić tych.Następnie w następnym kroku przygotujesz i zatwierdzasz zmiany w pozostałych dwóch plikach.
źródło
git commit -m "Implemented new feature XYZ" fileA.html fileB.html
działałoby dobrze bez konieczności używania poleceń git add. Pochodzę ze świata wywrotowego, w którym inscenizacja nie jest koncepcją, więc nie jestem przekonany co do przydatności inscenizacji gitŁatwiej jest zrozumieć użycie poleceń git
add
icommit
jeśli wyobrażasz sobie, że plik dziennika jest przechowywany w repozytorium na Github. Dla mnie typowy plik dziennika projektu może wyglądać następująco:Zwykle zaczynam dzień od
git pull
prośby i kończę gogit push
prośbą. Zatem wszystko w zapisie dnia odpowiada temu, co dzieje się między nimi. Każdego dnia wykonuję jedno lub więcej zadań logicznych , które wymagają zmiany kilku plików. Pliki edytowane podczas tego zadania są wymienione w indeksie.Każde z tych pod-zadań (tutaj Zadanie A i Zadanie B) jest indywidualnymi zatwierdzeniami.
git add
Polecenie dodaje pliki do listy „Lista plików Changed”. Ten proces jest również nazywany etapowaniem. Tegit commit
zapisy komenda / finalizuje zmian i odpowiednią listę indeksu wraz z niestandardowego komunikatu.Pamiętaj, że nadal zmieniasz tylko lokalną kopię repozytorium, a nie tę na Github. Po tym, tylko gdy wykonasz 'git push', wykonaj wszystkie te zarejestrowane zmiany, wraz z plikami indeksowymi dla każdego zatwierdzenia, zaloguj się do głównego repozytorium (na Github).
Na przykład, aby uzyskać drugi wpis w tym wyimaginowanym pliku dziennika, zrobiłbym:
W skrócie,
git add
igit commit
pozwala rozbić zmianę w głównym repozytorium na systematyczne logiczne zmiany podrzędne. Jak wskazywały inne odpowiedzi i komentarze, jest ich oczywiście o wiele więcej zastosowań. Jest to jednak jedno z najczęstszych zastosowań i główna zasada leżąca u podstaw Gita będącego wieloetapowym systemem kontroli wersji, w przeciwieństwie do innych popularnych, takich jak Svn.źródło
Aby rozwinąć odpowiedź Bena Jacksona , która jest w porządku, przyjrzyjmy się uważnie pierwotnemu pytaniu. (Zobacz jego odpowiedź, aby dowiedzieć się, dlaczego zawracasz sobie głowę typowymi pytaniami; to więcej o tym, co się dzieje ).
To nie jest całkiem w porządku. Kopie zapasowe i kontrola wersji są z pewnością powiązane - dokładnie, jak bardzo zależy od pewnych rzeczy, które w pewnym stopniu są kwestiami opinii - ale z pewnością istnieją pewne różnice, choćby celowe: kopie zapasowe są zwykle zaprojektowane do odzyskiwania po awarii (awaria maszyny, pożar niszczy cały budynek wraz ze wszystkimi nośnikami pamięci itp.). Kontrola wersji jest zwykle zaprojektowana dla bardziej szczegółowych interakcji i oferuje funkcje, których nie ma w przypadku kopii zapasowych. Kopie zapasowe są zwykle przechowywane przez jakiś czas, a następnie odrzucane jako „zbyt stare”: aktualna kopia zapasowa to wszystko, co się liczy. Kontrola wersji normalnie zapisuje na zawsze każdą zatwierdzoną wersję.
Tak i nie. Projekt Gita jest tutaj dość osobliwy. Istnieją systemy kontroli wersji, które nie wymagają oddzielnego etapu przejściowego. Na przykład Mercurial, który pod względem użytkowania jest bardzo podobny do Gita, nie wymaga oddzielnego
hg add
kroku, poza pierwszym, który wprowadza całkowicie nowy plik. W przypadku Mercurial używaszhg
polecenia, które wybiera zatwierdzenie, następnie wykonujesz swoją pracę, następnie uruchamiaszhg commit
i gotowe. W Git używaszgit checkout
, 1, potem wykonujesz swoją pracę, potem uruchamiaszgit add
, a potemgit commit
. Dlaczego dodatkowygit add
krok?Sekretem jest to, co Git nazywa różnie indeksem lub obszarem lub czasami - rzadko w dzisiejszych czasach - pamięcią podręczną . To są wszystkie nazwy dla tej samej rzeczy.
Nie, ale te są powiązane. ZAŚledzone plik jest jeden, który istnieje w indeksie jest git. Aby właściwie zrozumieć indeks, dobrze jest zacząć od zrozumienia zatwierdzeń.
Od wersji 2.23 Gita możesz używać
git switch
zamiastgit checkout
. W tym konkretnym przypadku te dwie komendy robią dokładnie to samo. Nowe polecenie istnieje, ponieważgit checkout
zostało przepełnione zbyt wieloma rzeczami; zostały podzielone na dwie oddzielne komendy,git switch
orazgit restore
, aby ułatwić i bezpieczniej korzystać z Gita.Commits
W Git, zatwierdzenie zapisuje pełną migawkę każdego pliku pliku, o którym Git wie. (O jakich plikach wie Git? Zobaczymy to w następnej sekcji.) Te migawki są przechowywane w specjalnej, tylko do odczytu, skompresowanej i pozbawionej duplikatów postaci, którą może odczytać tylko sam Git. . (W każdym zatwierdzeniu jest więcej rzeczy niż tylko ta migawka, ale to wszystko, co tutaj omówimy).
Usuwanie duplikatów pomaga w spacji: zwykle zmieniamy tylko kilka plików, a następnie wykonujemy nowe zatwierdzenie. Zatem większość plików w zatwierdzeniu jest w większości taka sama, jak pliki w poprzednim zatwierdzeniu. Po prostu ponownie wykorzystując te pliki bezpośrednio, Git oszczędza dużo miejsca: jeśli dotknęliśmy tylko jednego pliku, nowe zatwierdzenie zajmuje tylko miejsce na jedną nową kopię. Nawet wtedy jest skompresowany - czasami bardzo skompresowany, choć w rzeczywistości dzieje się to później - dzięki czemu
.git
katalog może być faktycznie mniejszy niż zawarte w nim pliki, gdy zostaną rozszerzone do zwykłych plików codziennego użytku. Usuwanie duplikatów jest bezpieczne, ponieważ zatwierdzone pliki są zamrożone na zawsze. Nikt nie może go zmienić, więc zatwierdzenie jest bezpieczne, jeśli zależy od kopii innych.Ponieważ przechowywane pliki są w tym specjalnym, zamrożonym na zawsze formacie, dostępnym tylko dla Git, Git musi rozszerzyć każdy plik do zwykłej codziennej kopii. Ta zwykła kopia nie jest kopią Gita : jest twoją kopią, którą możesz robić, co chcesz. Git po prostu do nich napisze, gdy mu to powiesz, abyś miał swoje kopie do pracy. Te użyteczne kopie znajdują się w twoim drzewie roboczym lub roboczym .
Oznacza to, że kiedy sprawdzasz jakieś konkretne zatwierdzenie, automatycznie pojawiają się dwa kopie każdego pliku:
Git ma zamrożoną kopię przez cały czas Git-ified w bieżącym zatwierdzeniu . Nie możesz zmienić tej kopii (chociaż możesz oczywiście wybrać inny zatwierdzenie lub utworzyć nowe zatwierdzenie).
W swoim drzewie roboczym masz kopię w normalnym formacie. Możesz zrobić wszystko, co chcesz, używając dowolnego polecenia na swoim komputerze.
Inne systemy kontroli wersji (w tym Mercurial, jak wspomniano powyżej) zatrzymują się tutaj, z tymi dwoma kopiami. Po prostu zmodyfikuj swoją kopię drzewa roboczego, a następnie zatwierdź. Git ... nie.
Indeks
Pomiędzy tymi dwiema kopiami Git przechowuje trzecią kopię 2 każdego pliku. Ta trzecia kopia jest w formacie zamrożonym , ale w przeciwieństwie do kopii zamrożonej w zatwierdzeniu możesz ją zmienić. Aby to zmienić, używasz
git add
.Te
git add
środki dowodzenia zrobić kopię indeksu pliku dopasować kopię praca drzewo . Oznacza to, że mówisz Gitowi: zastąp zamrożoną, pozbawioną duplikatów kopię, która jest teraz w indeksie, kompresując moją zaktualizowaną kopię drzewa roboczego, usuwając jej duplikaty i przygotowując ją do zamrożenia w nowym zatwierdzeniu. Jeśli nie używaszgit add
, indeks nadal zawiera kopię zamrożonego formatu z bieżącego zatwierdzenia.Po uruchomieniu
git commit
Git pakuje wszystko, co jest w indeksie, a następnie używa jako nowej migawki. Ponieważ jest już w zamrożonym formacie i wstępnie zduplikowany, Git nie musi wykonywać dużo dodatkowej pracy.To wyjaśnia również, o co chodzi w nieśledzonych plikach . Nieśledzony plik to plik, który znajduje się w twoim drzewie roboczym, ale nie znajduje się teraz w indeksie Git . Nie ma znaczenia, w jaki sposób plik został zlikwidowany w tym stanie. Może skopiowałeś go z innego miejsca na swoim komputerze, do swojego drzewa roboczego. Może stworzyłeś to świeżo tutaj. Może w indeksie Gita była kopia, ale usunąłeś tę kopię za pomocą
git rm --cached
. Tak czy inaczej, istnieje kopia w twoim drzewie roboczym, ale nie ma kopii w indeksie Gita. Jeśli zrobisz teraz nowe zatwierdzenie, ten plik nie będzie w nowym zatwierdzeniu.Zauważ, że
git checkout
początkowo wypełnia indeks Gita z zatwierdzonego zatwierdzenia. Więc indeks zaczyna się dopasowywać do zatwierdzenia. Git również wypełnia twoje drzewo robocze z tego samego źródła. Tak więc początkowo wszystkie trzy pasują. Kiedy zmieniasz pliki w swoim drzewie roboczym igit add
je, teraz indeks i drzewo robocze są zgodne. Następnie uruchamiaszgit commit
i Git tworzy nowe zatwierdzenie z indeksu, a teraz wszystkie trzy pasują ponownie.Ponieważ Git tworzy nowe zatwierdzenia z indeksu, możemy przedstawić to w ten sposób: indeks Gita przechowuje następny commit, który planujesz wykonać. To ignoruje rozszerzoną rolę, jaką odgrywa indeks Gita podczas scalania z konfliktem, ale i tak chcielibyśmy to na razie zignorować. :-)
To wszystko - ale wciąż jest to dość skomplikowane! Jest to szczególnie trudne, ponieważ nie ma łatwego sposobu, aby dokładnie sprawdzić, co znajduje się w indeksie Gita. 3 Ale jest polecenie Git, które mówi ci, co się dzieje, w bardzo przydatny sposób, i to polecenie jest
git status
.2 Technicznie rzecz biorąc, to wcale nie jest kopia . Zamiast tego jest to odniesienie do pliku Git-ified, wstępnie zdeduplikowanego i wszystkiego. Jest tu również więcej rzeczy, takich jak tryb, nazwa pliku, numer tymczasowy i niektóre dane z pamięci podręcznej, aby Git działał szybko. Ale jeśli nie zaczniesz pracować z niektórymi poleceniami niskiego poziomu Gita -
git ls-files --stage
igit update-index
w szczególności-można tylko myśleć o nim jako kopia.3
git ls-files --stage
komenda pokaże nazwy i numery inscenizacji każdego pliku indeksu git, ale zwykle nie jest to bardzo przydatne w każdym razie.git status
Plik
git status
rzeczywistości polecenie działa, uruchamiając dwa oddzielnegit diff
polecenia (a także wykonując inne przydatne rzeczy, takie jak wskazanie, w której gałęzi się znajdujesz).Pierwsza
git diff
porównuje aktualne zatwierdzenie - które, pamiętaj, jest zamrożone na zawsze - z tym, co znajduje się w indeksie Gita. W przypadku plików, które są takie same , Git w ogóle nic nie powie. W przypadku plików, które są różne , Git poinformuje Cię, że ten plik jest przygotowywany do zatwierdzenia . Obejmuje to wszystkie nowe pliki, jeśli popełnić nie masub.py
w nim, ale indeks musi miećsub.py
w nim, a następnie ten plik zostanie dodana i żadnych usuniętych plików, które były (i są) w popełnić, ale nie są w indeks już (git rm
być może).Drugi
git diff
porównuje wszystkie pliki w indeksie Gita z plikami w twoim drzewie roboczym. W przypadku plików, które są takie same , Git nic nie mówi. W przypadku plików, które są różne , Git poinformuje Cię, że ten plik nie jest przygotowywany do zatwierdzenia . W przeciwieństwie do pierwszego porównania, ta konkretna lista nie zawiera plików, które są całkowicie nowe: jeśli plikuntracked
istnieje w twoim drzewie roboczym, ale nie w indeksie Git, Git po prostu dodaje go do listy nieśledzonych plików . 4Na końcu, po zgromadzeniu tych nieśledzonych plików na liście,
git status
ogłosi również nazwy tych plików, ale jest specjalny wyjątek: jeśli nazwa pliku jest wymieniona w.gitignore
pliku, to pomija tę ostatnią listę. Zwróć uwagę, że umieszczenie śledzonego pliku - takiego, który jest w indeksie Gita - w a.gitignore
nie ma tu żadnego wpływu : plik znajduje się w indeksie, więc jest porównywany i zatwierdzany, nawet jeśli jest wymieniony w.gitignore
. Plik ignorowania pomija tylko skargi dotyczące „pliku nieśledzonego”. 54 W przypadku korzystania z krótkiej wersji
git status
-git status -s
—nieśledzone pliki nie są tak oddzielone, ale zasada jest taka sama. Gromadzenie plików w ten sposób pozwala równieżgit status
podsumować kilka nazw plików bez śledzenia, czasami po prostu drukując nazwę katalogu. Aby uzyskać pełną listę, użyjgit status -uall
lubgit status -u
.5 Wyświetlanie pliku powoduje również masowe dodawanie wielu operacji na plikach , takich jak
git add .
lubgit add *
pomijanie nieśledzonego pliku. Ta część staje się trochę bardziej skomplikowana, ponieważ możesz użyćgit add --force
do dodania pliku, który normalnie zostałby pominięty. Istnieją inne, zwykle drobne, specjalne przypadki, które sumują się do tego: plik.gitignore
może być lepiej nazwany.git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-them
lub coś równie nieporęcznego. Ale to zbyt śmieszne, więc.gitignore
tak jest.git add -u
,git commit -a
ItpJest kilka przydatnych skrótów, o których warto wiedzieć:
git add .
doda wszystkie zaktualizowane pliki w bieżącym katalogu i dowolnym podkatalogu. Szanuje to.gitignore
, więc jeśli plik, który obecnie nie jest śledzony, nie jest przedmiotem reklamacjigit status
, nie zostanie automatycznie dodany.git add -u
automatycznie doda wszystkie zaktualizowane pliki w dowolnym miejscu twojego drzewa roboczego . 6 Dotyczy to tylko śledzonych plików. Zauważ, że jeśli usunąłeś kopię drzewa roboczego, spowoduje to również usunięcie kopii indeksu (git add
robi to jako część jego dopasowania indeksu do drzewa roboczego ).git add -A
jest jak bieganiegit add .
z najwyższego poziomu twojego drzewa roboczego (ale zobacz przypis 6).Poza tym możesz biegać
git commit -a
, co z grubsza odpowiada 7 bieganiu,git add -u
a następniegit commit
. Oznacza to, że uzyskujesz to samo zachowanie, które jest wygodne w Mercurial.Generalnie odradzam
git commit -a
wzorzec: uważam, że lepiej jestgit status
często go używać , uważnie przyjrzeć się wynikowi , a jeśli stan nie jest taki, jakiego się spodziewałeś, dowiedz się, dlaczego tak jest. Używającgit commit -a
, zbyt łatwo jest przypadkowo zmodyfikować plik i zatwierdzić zmianę, której nie zamierzałeś zatwierdzić. Ale to głównie kwestia gustu / opinii.6 Jeśli Twoja wersja Gita jest starsza niż Git 2.0, bądź ostrożny:
git add -u
działa tylko w bieżącym katalogu i podkatalogach, więc najpierw musisz wspiąć się na najwyższy poziom swojego drzewa roboczego. Plikgit add -A
Opcja ma podobny problem.7 Mówię z grubsza równoważne, ponieważ
git commit -a
faktycznie działa poprzez utworzenie dodatkowego indeksu i użycie tego innego indeksu do wykonania zatwierdzenia. Jeśli zatwierdzenie zadziała , uzyskasz taki sam efekt jak zrobieniegit add -u && git commit
. Jeśli zatwierdzenie nie zadziała - jeśli sprawisz, że Git pominie zatwierdzenie na dowolny z wielu sposobów, które możesz to zrobić - wtedy żadne pliki nie sągit add
później -edowane, ponieważ Git wyrzuca tymczasowy dodatkowy indeks i wraca do używania indeksu głównego .Istnieją dodatkowe komplikacje, które pojawiają się, jeśli używasz
git commit --only
tutaj. W tym przypadku Git tworzy trzeci indeks i sprawy stają się bardzo skomplikowane, szczególnie jeśli używasz punktów zaczepienia przed zatwierdzeniem. To kolejny powód, aby używać oddzielnychgit add
operacji.źródło
Strefa przejściowa pomaga nam tworzyć zobowiązania z większą elastycznością. Mówiąc o rzemiośle, mam na myśli rozbicie zatwierdzeń na logiczne jednostki. Jest to bardzo ważne, jeśli potrzebujesz oprogramowania, które można konserwować. Najbardziej oczywisty sposób, w jaki możesz to osiągnąć:
Możesz pracować nad wieloma funkcjami / błędami w jednym katalogu roboczym i nadal tworzyć znaczące zatwierdzenia. Posiadanie jednego katalogu roboczego zawierającego całą naszą aktywną pracę jest również bardzo wygodne. (Można to zrobić bez obszaru przemieszczania, tylko pod warunkiem, że zmiany nigdy nie nakładają się na plik. Masz również dodatkową odpowiedzialność za ręczne śledzenie, czy się nakładają)
Więcej przykładów można znaleźć tutaj: Zastosowania indeksu
A najlepsze jest to, że zalety nie kończą się na tej liście przepływów pracy. Jeśli pojawi się wyjątkowy przepływ pracy, możesz być prawie pewien, że strefa przejściowa Ci pomoże.
źródło
Widzę sens w używaniu stage do zmniejszania commits, o czym wspominali @Ben Jackson i @Tapashee Tabassum Urmi i czasami używam go do tego celu, ale używam go głównie do powiększania moich zatwierdzeń! oto mój punkt widzenia:
Powiedzmy, że chcę dodać małą funkcję, która wymaga kilku mniejszych kroków. Nie widzę sensu w osobnym zatwierdzaniu dla mniejszych kroków i zalewaniu mojej osi czasu. Jednak chcę zapisać każdy krok i wrócić, jeśli to konieczne,
Po prostu wykonuję mniejsze kroki jeden na drugim, a kiedy uznam, że jest to warte zobowiązania, zobowiązuję się. W ten sposób usuwam niepotrzebne zatwierdzenia z osi czasu, ale mogę cofnąć (wyewidencjonować) ostatni krok.
Widzę inne sposoby na zrobienie tego (uproszczenie historii git), z których możesz skorzystać w zależności od swoich preferencji:
źródło
To jak pole wyboru, które umożliwia wybór plików do zatwierdzenia.
na przykład, jeśli edytowałem
fileA.txt
ifileB.txt
.Ale chcę zatwierdzić zmianyfileA.txt
tylko. ponieważ jeszcze nie skończyłemfileB.txt
.Mogę po prostu użyć
git add fileA.txt
i zatwierdzić użyciegit commit -m "changed fileA.txt"
i kontynuować pracę,fileB.txt
a po zakończeniu mogęfileB.txt
łatwo zatwierdzićźródło