Utwórz łatkę git na podstawie zmian w bieżącym katalogu roboczym


878

Powiedz, że mam niezatwierdzone zmiany w moim katalogu roboczym. Jak mogę zrobić łatkę z tych bez konieczności tworzenia zatwierdzenia?


29
Zaakceptowana odpowiedź powinna zostać prawdopodobnie zmieniona, ponieważ druga odpowiedź jest prawie czterokrotnie bardziej popularna.
Tim Ogilvy

5
@TimOgilvy zgodził się. OP powinien to zrobić. Druga odpowiedź jest znacznie bardziej popularna i daje więcej informacji
John Demetriou

1
Myślę, że warto też wspomnieć, że potrzebujesz łatki od nieproszonych zmian w tytule.
2i3r

Odpowiedzi:


401

git diffdla zmian nieetapowych. git diff --cacheddla etapowych zmian.


12
tak, git diff jest odwrotnością zastosowania git
Spike Gronim

33
git format-patchzawiera także binarne różnice i niektóre meta informacje. Właściwie to byłby najlepszy wybór do tworzenia łatki, ale afaik to działa tylko w przypadku sprawdzonych źródeł / zmian, prawda?
Eric

20
Czasami przydatne może być utworzenie łatki względem bieżącego katalogu. Aby to osiągnąć, użyjgit diff --relative
ejboy

30
git diff> a.patch, aby zapisać go do pliku
qasimzee

139
Krótko mówiąc sarkastycznie, poniższa odpowiedź jest bardziej pomocna.
Air

1864

Jeśli nie zatwierdziłeś jeszcze zmian, to:

git diff > mypatch.patch

Ale czasami zdarza się, że część rzeczy, które robisz, to nowe pliki, które nie są śledzone i nie będą w twoich wynikach git diff. Tak więc jednym ze sposobów na wykonanie poprawki jest ułożenie wszystkiego dla nowego zatwierdzenia (dla git addkażdego pliku lub po prostu git add .), ale nie wykonanie zatwierdzenia, a następnie:

git diff --cached > mypatch.patch

Dodaj opcję „binarną”, jeśli chcesz dodać pliki binarne do łatki (np. Pliki mp3):

git diff --cached --binary > mypatch.patch

Możesz później zastosować łatkę:

git apply mypatch.patch

Uwaga: możesz także użyć --stagedjako synonimu --cached.


127
Dziękuję bardzo za przykład. W przeciwieństwie do przyjętej odpowiedzi pokazujesz, jak to zrobić, a nie tylko rozmawiasz. Bardzo pomocny i działał dla mnie bezbłędnie :)
nuala

4
Zrobiłem dokładnie to i dostałem komunikat „fatal: nierozpoznany” po uruchomieniu git Apply. Masz pojęcie, co może to spowodować i jak to naprawić?
Witalij

6
@Vitaly: czy łatka jest czytelna, jeśli otworzysz ją za pomocą edytora tekstu? powinien być czysty, bez dziwnych znaków, na przykład jeśli ustawione jest ustawienie color.diff, łatka będzie zawierała niektóre „kolorowe znaki”, które mogą sprawić, że „zastosowanie git” nie powiedzie się, w takim przypadku spróbuj git diff --no-color. W przeciwnym razie wygląda to na problem z kodowaniem.
jcarballo

3
Powiązane z „nowymi plikami, które nie są śledzone”: „git diff” i „git diff --cached” działają tylko wtedy, gdy najpierw zostało wywołane „git add <plik>”. (Jestem nowy, żeby zacząć i zastanawiałem się, dlaczego za każdym razem dostaję pustą łatę)
Anonimowy

5
To dość łatwo wyciągnęło mnie z dziwnego piekła scalania / rebase, dzięki :)
John Hunt

86

git diffi git applybędzie działać dla plików tekstowych, ale nie będzie działać dla plików binarnych.

Możesz łatwo utworzyć pełną łatkę binarną, ale będziesz musiał utworzyć tymczasowe zatwierdzenie. Po dokonaniu tymczasowych zatwierdzeń możesz utworzyć łatkę za pomocą:

git format-patch <options...>

Po utworzeniu poprawki uruchom następujące polecenie:

git reset --mixed <SHA of commit *before* your working-changes commit(s)>

Spowoduje to wycofanie tymczasowych zatwierdzeń. Ostateczny wynik pozostawia kopię roboczą (celowo) brudną z tymi samymi zmianami, co pierwotnie.

Po stronie odbierającej możesz użyć tej samej sztuczki, aby zastosować zmiany do kopii roboczej, bez posiadania historii zmian. Po prostu zastosuj łatki i git reset --mixed <SHA of commit *before* the patches>.

Pamiętaj, że może być konieczne zsynchronizowanie całej tej opcji. Widziałem błędy podczas stosowania poprawek, gdy osoba, która je stworzyła, nie usunęła tylu zmian, co ja. Prawdopodobnie istnieją sposoby, aby to zadziałało, ale nie zagłębiłem się w to.


Oto jak stworzyć te same łatki w Tortoise Git (nie polecam korzystania z tego narzędzia):

  1. Zatwierdź zmiany robocze
  2. Kliknij prawym przyciskiem myszy główny katalog oddziału, a następnie kliknij Tortoise Git->Create Patch Serial
    1. Wybierz dowolny zakres, który ma sens ( Since: FETCH_HEADzadziała, jeśli jesteś dobrze zsynchronizowany)
    2. Utwórz łatki
  3. Kliknij prawym przyciskiem myszy główny katalog oddziału, a następnie kliknij Tortise Git->Show Log
  4. Kliknij zatwierdzenie prawym przyciskiem myszy przed tymczasowymi zatwierdzeniami, a następnie kliknijreset "<branch>" to this...
  5. Wybierz Mixedopcję

I jak je zastosować:

  1. Kliknij prawym przyciskiem myszy główny katalog oddziału, a następnie kliknij Tortoise Git->Apply Patch Serial
  2. Wybierz poprawne łatki i zastosuj je
  3. Kliknij prawym przyciskiem myszy główny katalog oddziału, a następnie kliknij Tortise Git->Show Log
  4. Kliknij zatwierdzenie prawym przyciskiem myszy przed zatwierdzeniem (zatwierdzeniami) łatki i kliknijreset "<branch>" to this...
  5. Wybierz Mixedopcję

5
Technicznie wymaga to utworzenia zatwierdzenia, którego OP chciał uniknąć, ale jest to tymczasowe i odpowiedź jest przydatna niezależnie.
davenpcj

33

Aby utworzyć łatkę ze zmodyfikowanymi i nowymi plikami (przemieszczanymi), możesz uruchomić:

git diff HEAD > file_name.patch

Dzięki, w moim przypadku ta odpowiedź działa, ale git diff --cached > mypatch.patchnie działa.
wydobycie

Mam pytanie: może file_name.patchbyć użyte przez patchpolecenie? Czy są ze sobą kompatybilne?
Rakshith Ravi

git diff + git diff --cached / staged == Git diff HEAD (pokaż wszystkie zmiany od ostatniego zatwierdzenia)
K. Symbol

20

Podoba mi się:

git format-patch HEAD~<N>

gdzie <N>jest liczbą ostatnich zatwierdzeń do zapisania jako łatki.

Szczegóły dotyczące korzystania z polecenia znajdują się w DOC

UPD
Tutaj możesz znaleźć, jak je następnie zastosować.

UPD Dla tych, którzy nie mieli pojęcia o format-patch
dodaniu aliasu:

git config --global alias.make-patch '!bash -c "cd ${GIT_PREFIX};git add .;git commit -m ''uncommited''; git format-patch HEAD~1; git reset HEAD~1"'

Następnie w dowolnym katalogu repozytorium projektu uruchom:

git make-patch

To polecenie utworzy 0001-uncommited.patchw bieżącym katalogu. Łatka będzie zawierać wszystkie zmiany i nieśledzone pliki widoczne dla następnego polecenia:

git status .

@jcarballo: Zaktualizowałem odpowiedź. Uprzejmie informuj mnie o swoich uwagach.
Eugen Konkov

2
Jest prostszy sposób niż utworzenie zatwierdzenia i nieprzyzwoicie. git diff --cached --binary
Gaurav Agarwal

9

Jeśli chcesz robić pliki binarne, daj --binaryopcję podczas uruchamiania git diff.


0

Możemy również określić pliki, aby uwzględnić tylko pliki ze zmianami względnymi, szczególnie gdy obejmują one wiele katalogów np

git diff ~/path1/file1.ext ~/path2/file2.ext...fileN.ext > ~/whatever_path/whatever_name.patch

Nie znalazłem tego w odpowiedziach lub komentarzach, które są odpowiednie i poprawne, więc postanowiłem je dodać. Jawne jest lepsze niż niejawne!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.