Zatwierdź tylko część pliku w Git

2764

Kiedy wprowadzam zmiany do pliku w Git, jak mogę zatwierdzić tylko niektóre zmiany?

Na przykład, jak mogę zatwierdzić tylko 15 wierszy z 30 wierszy, które zostały zmienione w pliku?

freddiefujiwara
źródło
3
powiązane stackoverflow.com/q/34609924/52074 : jeśli chcesz podzielić kawałek na mniejsze kawałki.
Trevor Boyd Smith
Podsumowanie: pod względem możliwości: git gui= git add -e> git add -i -p; pod względem wygody: git gui> git add -i -p> git add -e. Tak: wybrać git gui, gdy masz dostęp do X. wybrać git add -i -pdla prostych rzeczy, a gdy nie masz lub chcesz używać X. git add -edo kompleksowego inscenizacji bez X.
Penghe Geng

Odpowiedzi:

3687

Możesz użyć git add --patch <filename>(lub -pw skrócie), a git zacznie rozkładać twój plik na coś, co według niego jest sensownym „kawałkiem” (części pliku). Następnie wyświetli się następujące pytanie:

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

Oto opis każdej opcji:

  • y zrób ten przystojniak do następnego zatwierdzenia
  • n nie wystawiaj tego przystojniaka do następnego zatwierdzenia
  • qporzucić; nie wystawiaj tego przystojniaka ani żadnego z pozostałych przystojniaków
  • a ustaw ten kawałek i wszystkie późniejsze kawałki w pliku
  • d nie wystawiaj tego fragmentu ani żadnego z późniejszych fragmentów w pliku
  • g wybierz przystojniak, aby przejść do
  • / wyszukaj przystojniak pasujący do podanego wyrażenia regularnego
  • j zostaw ten przystojniak niezdecydowany, patrz następny niezdecydowany przystojniak
  • J zostaw ten przystojniak niezdecydowany, patrz następny przystojniak
  • k zostaw ten przystojniak niezdecydowany, patrz poprzedni niezdecydowany przystojniak
  • K zostaw ten przystojniak niezdecydowany, patrz poprzedni przystojniak
  • s podzielić obecny przystojniak na mniejsze przystawki
  • e ręcznie edytować bieżący przystojniak
  • ? wydrukuj pomoc przystojniaka

Jeśli pliku nie ma jeszcze w repozytorium, możesz to zrobić najpierw git add -N <filename>. Następnie możesz kontynuować git add -p <filename>.

Następnie możesz użyć:

  • git diff --staged aby sprawdzić, czy wprowadzono prawidłowe zmiany
  • git reset -p na scenie błędnie dodali przystojniaki
  • git commit -v aby zobaczyć swoje zatwierdzenie podczas edycji wiadomości zatwierdzenia.

Zauważ, że jest to coś zupełnie innego niż git format-patchpolecenie, którego celem jest parsowanie zatwierdzonych danych do .patchplików.

Referencje na przyszłość: Git Tools - Interactive Staging

mac
źródło
83
Warto zauważyć, że -p/--patchjest to skrót do akcji łatania wewnątrz -i/--interactivepolecenia, które inicjuje przydatny tryb interaktywny .
tutuDajuju,
5
> Co się stanie, jeśli ten plik jest już przemieszczany? Wyświetli tylko niestopniowe zmiany. Tak samo jak git diffrobi.
Eugen Konkov
3
Jak mogę ręcznie edytować bieżący przystojniak? Nie wiem co robić po wpisaniu e.
Hunsu,
23
Po naciśnięciu przycisku e, można edytować ręcznie, zastępując kawał +lub -przez#
veksen
1
to jest świetne, ale teraz jak mam to zrobić? jeśli to zrobię git push, powie to już aktualne. a jeśli to zrobię, git diffzobaczę przystojniaków, o których mówiłem n. jeśli to zrobię, git diff --stagedzobaczę zatwierdzenie, które chcę wcisnąć. Zakładając, że mogę wcisnąć przycisk zatwierdzenia, jak usunąć fragmenty, o których mówiłem no?
chovy
250

Możesz użyć git add --interactivelub , a następnie ( nie ); zobacz Tryb interaktywny na stronie git-add lub po prostu postępuj zgodnie z instrukcjami.git add -p <file>git commit git commit -a

Modern Git ma również git commit --interactive(i git commit --patch, który jest skrótem do opcji łatki w interaktywnym zatwierdzeniu).

Jeśli wolisz robić to z GUI, możesz użyć git-gui . Możesz po prostu zaznaczyć fragmenty, które chcesz uwzględnić w zatwierdzeniu. Osobiście uważam to za łatwiejsze niż używanie git add -i. Inne GUI Git, takie jak QGit lub GitX, również mogą mieć tę funkcję.

Jakub Narębski
źródło
1
Co ciekawe, witryna windows.github.com miała obsługę częściowych zatwierdzeń plików, ale wydaje się, że ostatnio ją upuściła.
Juri
1
@Juri Myślę, że obsługa częściowych zatwierdzeń plików powróciła.
Ela782
@Juri Nie ma za co. Właściwie nigdy nie zauważyłem, że był tam wcześniej - widziałem to w zeszłym tygodniu i pomyślałem „och, co za niesamowita nowa funkcja”! :-)
Ela782
1
Obecnie windows.github.com przekierowuje na zmieniony branding GitHub Desktop, który jest ładniejszy niż Git GUI i obsługuje częściowe zatwierdzenia ... ale nie obsługuje podpisywania zatwierdzeń. Westchnienie.
147

git gui zapewnia tę funkcjonalność w widoku różnic. Kliknij prawym przyciskiem myszy interesującą Cię linię, a zobaczysz pozycję menu „etap tej linii do zatwierdzenia”.

Ionuț G. Stan
źródło
13
w przypadku złożonych łatek jest to dla mnie najszybsze podejście.
hochl
7
Jest to bardzo wydajny i intuicyjny sposób dodawania zmian w obszarze pomostowym w drobnoziarnisty sposób. Można również wybrać wiele wierszy i wszystkie zmiany w ramach tego wyboru zostaną dodane.
jox
Pamiętaj, że nie jest gitk, ale jest dołączony do Git Bash dla Windows; powinieneś mieć dla niego pozycję menu Start lub uruchomić ją za pomocą polecenia git gui. Jest też coś, stage this hunkco jest prawdopodobnie bardziej przydatne niż stage this line. Może być nowy, ponieważ ta odpowiedź została stworzona 10 lat temu.
Chris
82

Uważam, że git add -e myfilejest to najłatwiejszy sposób (przynajmniej moje preferencje), ponieważ po prostu otwiera edytor tekstu i pozwala wybrać linię, którą chcesz wystawić, a która nie. Odnośnie poleceń edycji:

dodana treść:

Dodana treść jest reprezentowana przez linie rozpoczynające się od „+”. Możesz zapobiec przemieszczaniu dowolnych linii dodawania, usuwając je.

usunięta treść:

Usunięte treści są reprezentowane przez linie rozpoczynające się od „-”. Możesz zapobiec przemieszczaniu ich usuwania, konwertując „-” na „” (spację).

zmodyfikowana treść:

Zmodyfikowana treść jest reprezentowana przez linie „-” (usuwanie starej zawartości), a następnie linie „+” (dodawanie zawartości zastępczej). Możesz zapobiec przemieszczaniu modyfikacji poprzez konwersję linii „-” na „” i usunięcie linii „+”. Uwaga: modyfikacja tylko połowy pary może wprowadzić mylące zmiany w indeksie.

Wszystkie szczegóły dotyczące git addsą dostępne nagit --help add

theFreedomBanana
źródło
7
Byłoby to bardziej przydatne, gdyby gdzieś było jasne wyjaśnienie, jak faktycznie wybrać te wiersze (tj. Rzeczywiste polecenia do wprowadzenia). Nie mogłem go znaleźć w dokumentacji. Czy możesz dodać referencję?
Alex
4
Dla tych, którzy nie lubią opcji skrótu, -ejest --edit.
Kolyunya
2
@Alex Cytaty referencyjne dodane przez FreedomBanana pochodzą z sekcji EDYCJA PATCHÓW wgit --help add
Randall
8
Jest to jedyna odpowiedź (wymagająca tylko git), która rozwiązuje problem dodawania / usuwania linii, gdy nie można zmniejszyć porcji sw interaktywnym trybie łatki.
cdosborn
3
Pomocne może być zrozumienie, że to polecenie ( git add -e) * nie zmienia * zawartości pliku na dysku. Po prostu przenosi część zmian ze sceny niestacjonarnej na etapową (indeks).
Penghe Geng
44

Jeśli używasz vima, możesz wypróbować doskonałą wtyczkę o nazwie fugitive .

Możesz zobaczyć różnicę pliku między kopią roboczą a indeksem :Gdiff, a następnie dodać do indeksu wiersze lub porcje za pomocą klasycznych poleceń vim diff, takich jak dp. Zapisz zmiany w indeksie i zatwierdź za pomocą :Gcommit, i gotowe.

Bardzo dobre wprowadzające screencasty tutaj (patrz zwłaszcza część 2 ).

François
źródło
Dziękuję bardzo za te linki. Dokładnie to samo, czego potrzebuję. Zwłaszcza :diffget/:diffputw trybie wizualnym, w którym mogę wybrać określone linie, które chcę zresetować / zatwierdzić. Upewnij się więc jeszcze raz: vim jest niesamowity.
goodniceweb
30

Zdecydowanie polecam korzystanie z SourceTree od Atlassian. (To nic nie kosztuje.) To sprawia, że ​​jest to trywialne. Możesz szybko i łatwo ustawiać poszczególne fragmenty kodu lub poszczególne wiersze kodu.

wprowadź opis zdjęcia tutaj

Bob Stein
źródło
1
Zgadzam się, że SourceTree jest dobrym narzędziem do tego celu, ponieważ daje ci bardziej szczegółową kontrolę niż jest to możliwe za pomocą wiersza poleceń.
18
@cupcake Argumentowałbym przeciwnie, widząc, że SourceTree prawdopodobnie używa tych plików wykonywalnych git z linii poleceń, z natury rzeczy zawsze będzie możliwe wykonywanie tych samych (lub więcej) drobiazgowych działań za pośrednictwem „wiersza poleceń”.
tutuDajuju
2
Bez względu na drobiazgowy argument gorąco polecam SourceTree, ponieważ inscenizacja kawałków i pojedynczych linii jest bardzo łatwa: i.imgur.com/85bNu4C.png
Mars Robertson
1
@tutuDajuju W tym przypadku nie jestem pewien, czy to prawda. SourceTree ma możliwość wybrania, które fragmenty etap po linii . Nie musisz wystawiać całego przystojniaka; możesz ustawić 2 linie w środku przystojniaka. Nie mam jednak pojęcia, jak to osiąga. (W tej chwili próbuję obejść niezdolność SourceTree do przygotowania poszczególnych linii dla nieśledzonego pliku. Wylądowałem tutaj, szukając obejścia, ale okazało się, że git najwyraźniej nie oferuje zdolności linia po linii w ogóle. Przynajmniej nie w prosty sposób.)
jpmc26,
1
@Sun możesz kliknąć linię 50 i Shift + kliknąć linię 100, a następnie etap. Możesz łatwo ustawić linię 50-100 w Sourcetree :)
ryan123
26

Warto zauważyć, że do wykorzystania git add --patchdla nowego pliku trzeba najpierw dodać plik do indeksu z git add --intent-to-add:

git add -N file
git add -p file
użytkownik1338062
źródło
23

Kiedy wprowadzę wiele zmian i ostatecznie skończę tworzyć kilka zatwierdzeń na podstawie tych zmian, chcę tymczasowo zapisać swój punkt początkowy przed inscenizacją.

Lubię to:

$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 1st commit"
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 2nd commit"
$ git stash pop

Whymarrh odpowiada na to, co zwykle robię, z wyjątkiem tego, że czasami jest wiele zmian i mogę powiedzieć, że popełniam błąd podczas wystawiania różnych rzeczy, i chcę stanu, w którym mogę popaść na drugie przejście.

jdsumsion
źródło
12

Jeśli używasz emacsa, spójrz na Magit , który zapewnia interfejs git dla emacsa. Całkiem dobrze obsługuje pomostowe fragmenty (części plików).

Mark van Lent
źródło
Często potykam się o polecenie git, które chce otworzyć edytor, gdy uruchamiam go z okna powłoki Mx. Czy magit przechwytuje to szaleństwo i otwiera na to tylko nowy bufor? (proszę, nie ma podpowiedzi demona-tła; mimo to dziękuję, ale życie jest za krótkie).
user2066657
Nie, o ile mogę stwierdzić, nie przechwytuje tego. Ale nie wierz mi na słowo, ponieważ (1) prawie nigdy nie używam okna powłoki w Emacsie i (2) zwykle używam emacsclient. Powiedziawszy to, jeśli emacsclient jest dla ciebie opcją, to przynajmniej zapobiegło otwarciu dodatkowego okna z emacsem i otwarciu bufora „COMMIT_EDITMSG” w moim istniejącym oknie Emacsa.
Mark van Lent
10

Intellij IDEA (i chyba wszystkie inne produkty z tej serii) ma wbudowaną obsługę częściowych zatwierdzeń od wersji v2018.1

wprowadź opis zdjęcia tutaj

Holger Brandl
źródło
9

Dla tych, którzy używają rozszerzeń Git :

W oknie Zatwierdź wybierz plik, który chcesz częściowo zatwierdzić, a następnie zaznacz tekst, który chcesz zatwierdzić, w prawym okienku, a następnie kliknij prawym przyciskiem myszy zaznaczenie i wybierz polecenie „Stwórz wybrane linie” z menu kontekstowego.

srgstm
źródło
2
Skrót klawiaturowy w rozszerzeniach Gita dla „Wybranych linii etapów” jest sbardzo przydatny do szybkiego przemieszczania części plików do zatwierdzenia.
Alchemistmatt
8

Podobnie jak odpowiedź jdsumsion, możesz także ukryć swoją obecną pracę, ale następnie użyć narzędzia difftool, takiego jak meld, aby wyciągnąć wybrane zmiany ze schowka. W ten sposób możesz nawet edytować fragmenty ręcznie bardzo łatwo, co jest trochę uciążliwe, gdy git add -p:

$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m "some message"
$ git stash pop

Zastosowanie metody ukrywania daje możliwość przetestowania, czy kod nadal działa, zanim go zatwierdzisz.

derhoch
źródło
to działa dobrze, ale jeśli używasz git commit --amend, wydaje się, że nie możesz później wyskoczyć z ukrycia, czy jest na to sposób?
Mark
7

Dodając poprzednią odpowiedź, jeśli wolisz korzystać z wiersza poleceń, wpisanie git add -e myfiledaje Ci możliwość wyboru linii po linii, co chcesz zatwierdzić, ponieważ to polecenie otworzy edytor z różnicami, na przykład:

wprowadź opis zdjęcia tutaj

Jak być może wiesz, linie zaczynające się od +są dodatkami, linie zaczynające się od są usuwane -. Więc:

  • Aby nie wystawiać dodatku, po prostu usuń ten wiersz.
  • Aby nie wprowadzać usunięcia, zastąp -go spacją .

Oto, co git add -hmówi o dodawaniu plików w ten sposób (łatanie plików):

dodana zawartość Dodana treść jest reprezentowana przez linie rozpoczynające się od „+”. Możesz zapobiec przemieszczaniu dowolnych linii dodawania, usuwając je.

usunięta treść: usunięta treść jest reprezentowana przez linie rozpoczynające się od „-”. Możesz zapobiec przemieszczaniu ich usuwania, konwertując „-” na „” (spację).

zmodyfikowana treść: zmodyfikowana treść jest reprezentowana przez linie „-” (usuwanie starej zawartości), a następnie linie „+” (dodawanie zawartości zastępczej). Możesz zapobiec przemieszczaniu modyfikacji poprzez konwersję linii „-” na „” i usunięcie linii „+”. Uwaga: modyfikacja tylko połowy pary może wprowadzić mylące zmiany w indeksie.

Uwaga: nie zmieniaj zawartości pliku, nie jest to dobre miejsce do zrobienia tego. Wystarczy zmienić operatorów usuniętych lub dodanych linii.

Beto Aveiga
źródło
Jaka poprzednia odpowiedź? Odpowiedzi są przechowywane na podstawie liczby punktów, które mają. Twoja odpowiedź jest teraz w innym miejscu niż wtedy, gdy ją napisałeś, w porównaniu do innych odpowiedzi.
KulaGGin
Uważam, że przywołana odpowiedź pochodzi z @theFreedomBanana
K. Symbol
6

Wtyczka vim-gitgutter może tworzyć porcje bez opuszczania edytora vim

:GitGutterStageHunk

Oprócz tego zapewnia inne fajne funkcje, takie jak kolumna znaku różnicowego, jak w niektórych nowoczesnych IDE

Jeśli tylko część przystojniaka powinna być zainscenizowana zbiegiem

:Gdiff

umożliwia wówczas wybór zasięgu wizualnego :'<,'>diffputlub :'<,'>diffgetstopniowanie / cofanie indywidualnych zmian linii.

c0ffeeartc
źródło
4

Z TortoiseGit:

kliknij plik prawym przyciskiem myszy i użyj Context Menu → Restore after commit. Spowoduje to utworzenie kopii pliku w obecnej postaci. Następnie możesz edytować plik, np. W TortoiseGitMerge i cofnąć wszystkie zmiany, których nie chcesz zatwierdzać. Po zapisaniu tych zmian możesz zatwierdzić plik.

Fr0sT
źródło
4

Minęło 10 lat, odkąd zadano to pytanie. I mam nadzieję, że ta odpowiedź będzie dla kogoś przydatna. Jak wspomniano w odpowiedzi tutaj , gdzie GUI nie jest opcją, rozszerzenie crecord Andrew Shadury pomaga wprowadzić okno ncurses, w którym możemy wybrać linie do zatwierdzenia.

Skonfiguruj rozszerzenie w następujący sposób:

git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord

cd na repozytorium git i wywołaj go w następujący sposób:

git crecord

Spowoduje to wywołanie interfejsu ncurses, którego można używać, jak pokazano poniżej. Naciśnięcie następujących klawiszy w oknie ncurses spowoduje wykonanie pewnych czynności:

f       hunk toggle fold (arrow keys can also be used)
space   toggle hunk selection
a       toggle commit or amend
c       confirm and open commit window

Screencast pokazujący przykładowe użyciePrzykład

Bieg
źródło
3

Dla użytkowników Atom pakiet github zawiera interaktywną inscenizację w stylu git gui. Skróty można znaleźć w dokumentacji pakietu .

Korzystanie z Atom pozwala na pracę z motywem o ciemnym tle (domyślnie git guima białe tło).

Ioannis Filippidis
źródło
2

git-meld-index - cytowanie ze strony:

git-meld-index uruchamia meld - lub dowolny inny git difftool (kdiff3, diffuse itp.) - aby umożliwić Ci interaktywne wprowadzanie zmian w indeksie git (znanym również jako obszar testowania git).

Jest to podobne do funkcji git add -p i git add --interactive. W niektórych przypadkach meld jest łatwiejszy / szybszy w użyciu niż git add -p. Jest tak, ponieważ meld pozwala na przykład:

  • zobacz więcej kontekstu
  • zobacz różnice między wierszami
  • edytuj ręcznie i zobacz aktualizacje „na żywo” diff (aktualizowane po każdym naciśnięciu klawisza)
  • przejdź do zmiany, nie mówiąc „n” do każdej zmiany, którą chcesz pominąć

Stosowanie

W repozytorium git uruchom:

git meld-index

Zobaczysz wyskakujące okno meld (lub skonfigurowanego git difftool) z:

LEWY : pliki tymczasowe zawierające katalog skopiowane z twojego drzewa roboczego

PRAWO : katalog tymczasowy z zawartością indeksu. Dotyczy to również plików, które nie są jeszcze w indeksie, ale zostały zmodyfikowane lub nie są śledzone w kopii roboczej - w tym przypadku zobaczysz zawartość pliku z HEAD.

Edytuj indeks (po prawej stronie), aż będzie szczęśliwy. Pamiętaj, aby zapisać w razie potrzeby.

Gdy skończysz, zamknij meld, a git-meld-index zaktualizuje indeks, aby pasował do zawartości katalogu tymczasowego po prawej stronie edytowanego właśnie meldu.

Croad Langshan
źródło
2

Jeśli jest na Windowsplatformie, moim zdaniem git guijest bardzo dobrym narzędziem do stage/ commitkilku wierszy z unstagedpliku

1. Hunk mądry:

  • Wybierz plik z unstagged Changessekcji
  • Kliknij prawym przyciskiem myszy fragment kodu, który musi być zainscenizowany
  • Wybierz Stage Hunk for commit

2. Linia mądra:

  • Wybierz plik z unstagged Changessekcji
  • Wybierz linię / linie, które mają być przemieszczane
  • Kliknij prawym przyciskiem myszy i wybierz Stage Lines for commit

3. Jeśli chcesz ustawić cały plik poza kilkoma liniami:

  • Wybierz plik z unstagged Changessekcji
  • naciśnij Ctrl+T (Stage file to commit)
  • Wybrany plik zostanie teraz przeniesiony do Staged Changessekcji
  • Wybierz linię / linie, które mają być przemieszczane
  • Kliknij prawym przyciskiem myszy i wybierz UnStage Lines for commit
Anvesh Yalamarthy
źródło
1

Jak pokazuje jedna odpowiedź powyżej, możesz użyć git add --patch filename.txt

lub krótki formularz git add -p filename.txt

... ale w przypadku plików już znajdujących się w twoim repozytorium lepiej jest użyć opcji --patch bezpośrednio w poleceniu commit (jeśli używasz wystarczająco najnowszej wersji git): git commit --patch filename.txt

... lub znowu skrócona forma git commit -p filename.txt

... a następnie używając wspomnianych kluczy (t / n itd.), do wyboru wierszy, które mają być zawarte w zatwierdzeniu.

Samuel Lampa
źródło
Co daje ci to „ git add -p filename.txt” poza tym, że jest mniej miejsca na błędy? Jeśli popsuniesz zmianę częściowego pliku, cofnięcie dodawania jest lepsze niż cofnięcie zatwierdzenia.
CTMacUser
Nie wiem dlaczego, ale kiedy mówię „n”, linia zostaje uwzględniona… a kiedy mówię „y” na 2. przystojniaku, również zostaje uwzględniona.
chovy
0

git-cola jest świetnym GUI i ma również tę wbudowaną funkcję. Wystarczy wybrać linie na scenę i nacisnąć S. Jeśli nie zostanie dokonany wybór, cały przystojniak jest wystawiany.

AndiDog
źródło