Jak zastosować poprawkę Git do pliku o innej nazwie i ścieżce?


105

Mam dwa repozytoria. W jednym dokonuję zmian w pliku ./hello.test. Zatwierdzam zmiany i tworzę łatkę z tego zatwierdzenia za pomocą git format-patch -1 HEAD. Teraz mam drugą repozytorium zawierającego plik, który ma te same treści jak hello.test ale jest umieszczony w innym katalogu pod inną nazwą: ./blue/red/hi.test. Jak mam się zabrać do zastosowania wyżej wymienionej poprawki do hi.testpliku? Próbowałem, git am --directory='blue/red' < patch_fileale to oczywiście narzeka, że ​​pliki nie mają takich samych nazw (o czym myślałem, że Gitowi to nie obchodzi?). Wiem, że prawdopodobnie mógłbym edytować różnice, aby zastosować je do tego konkretnego pliku, ale szukam rozwiązania poleceń.


Odpowiedzi:


101

Możesz utworzyć łatkę za pomocą, git diffa następnie zastosować ją za pomocą patchnarzędzia, które pozwala określić plik, do którego chcesz zastosować różnicę.

Na przykład:

cd first-repo
git diff HEAD^ -- hello.test > ~/patch_file

cd ../second-repo
patch -p1 blue/red/hi.test ~/patch_file

7
Ach, miło, nie pomyślałem o tym. Czy istnieje jednak sposób, aby to zrobić za pomocą poleceń Git, aby dane dotyczące zatwierdzenia (data i godzina, autor zatwierdzenia, komunikat o zatwierdzeniu) były takie same?
mart1n

2
Możliwe, że jest coś, co możesz zrobić z amlub apply, ale nie mogę tego znaleźć. Jeśli zauważysz, że często powielasz zmiany, może być lepsze rozwiązanie przy użyciu modułów podrzędnych lub dowolnego języka, który wybierzesz, do udostępniania kodu (np. W Rubim możesz wyodrębnić zduplikowany kod jako klejnot).
georgebrock

1
W rzeczywistości jest to związane z dokumentacją (pliki źródłowe to XML). Podmoduły nie są tak naprawdę opcją, ponieważ musiałbym przedstawić ich mocne argumenty w naszej istniejącej infrastrukturze.
mart1n

55

Istnieje proste rozwiązanie, które nie wymaga ręcznej edycji łatek ani zewnętrznego skryptu.

W pierwszym repozytorium (może to również wyeksportować zakres zatwierdzeń, użyj, -1jeśli chcesz wybrać tylko jedno zatwierdzenie):

git format-patch --relative <committish> --stdout > ~/patch

W drugim repozytorium:

git am --directory blue/red/ ~/patch

Zamiast używać --relativein git format-patch, innym rozwiązaniem jest użycie -p<n>opcji in w git amcelu nusunięcia katalogów ze ścieżki łatek, jak wspomniano w odpowiedzi na podobne pytanie .

Możliwe jest również uruchomienie git format-patch --relative <committish>bez rozszerzenia --stdouti wygeneruje zestaw .patchplików. Pliki te mogą być następnie doprowadzane bezpośrednio do git amz git am --directory blue/red/ path/to/*.patch.


9
To nadal opiera się na fakcie, że nazwy plików są takie same, prawda?
mart1n

3
Należy zauważyć, że --directoryopcja wymaga podania pełnej ścieżki katalogu względem katalogu głównego repozytorium; coś takiego jak --directory=./zmiana katalogu w podkatalogu w repozytorium nie zadziała.
Reid

1
Korzystanie --3wayz pomocy z does not exist in index:git am --3way --directory (relative-path) (patch)
Brent Bradburn

Użyj -kklawisza w obu poleceniach, aby nie usuwać pierwszej linii komunikatu o zatwierdzeniu.
ruvim

Używanie --3waynie tylko pomaga w przypadku błędów „nie istnieje w indeksie” (jak wskazał @nobar), ale także pozwala na prostą obsługę konfliktów przy scalaniu. Zamiast pozostawiać konfliktowe pliki nietknięte, dodawany jest blok konfliktu, który można następnie rozwiązać.
Daniel Wolf

12

Odpowiadając na moje pytanie skryptem, który właśnie to robi: https://github.com/mprpic/apply-patch-to-file

Zamiast ręcznie modyfikować plik poprawki, monituje użytkownika o plik docelowy, modyfikuje poprawkę i stosuje ją do repozytorium, w którym aktualnie się znajdujesz.


5

Opierając się na odpowiedzi @georgebrock, oto rozwiązanie, którego użyłem:

Najpierw utwórz pliki łatek jak zwykle (np. git format-patch commitA..commitB).

Następnie upewnij się, że repozytorium docelowe jest czyste (nie powinno być żadnych zmienionych ani nieśledzonych plików) i zastosuj takie łaty:

cd second-repo
git am ~/00*.patch

Dla każdego pliku poprawki zostanie wyświetlony komunikat o błędzie typu „błąd: XYZ nie istnieje w indeksie”. Możesz teraz ręcznie zastosować ten plik poprawki:

patch --directory blue/red < ~/0001-*.patch
git add -a
git am --continue

Musisz wykonać te trzy kroki dla każdego pliku poprawki.

Pozwoli to zachować oryginalny komunikat o zatwierdzeniu itp. Bez konieczności specjalnego git format-patchpolecenia lub edytowania plików łaty.


1
Dobra odpowiedź, myślę, że to najlepsza podstawa do wszelkiego rodzaju „niestandardowych” manipulacji łatkami. Robię to w 3 krokach. (1) Zobowiązanie się do tekstu - git format-patch -1 commitA --stdout > thing.diff; (2) Edytuj plik poprawki, dopóki nie zrobi tego, czego potrzebuję; (3) Tekst do zatwierdzenia, git am --3way thing.diff który ma tę zaletę, że możesz zaakceptować części łatki, które się nakładają, i użyć gitstandardowego procesu rozwiązywania konfliktów dla części, które tego nie robią.
Wszyscy jesteśmy Monica

2

Rozumiem, że te dwa pliki są dokładnie takie same w Twojej sytuacji, dlatego łatka prawdopodobnie się powiedzie.

Jednak w przypadku, gdy chcesz zastosować poprawkę do podobnego, ale nie do końca tego samego pliku, lub chcesz wykonać interaktywną łatkę, zastosujesz łączenie trójstronne.

Powiedzmy, że zmodyfikowałeś plik A, oznaczmy A~1jako poprzednią wersję i chcesz zastosować różnicę między A~1do Ado pliku B.

Otwórz narzędzie do łączenia trójstronnego, na przykład Beyond Compare, ścieżka lewego panelu to A, środkowy panel jest wspólnym przodkiem, więc ścieżka jest A~1, ścieżka prawego panelu to B. Następnie dolny panel pokazuje wynik zastosowania różnicy między A~1do Ado pliku B.

Poniższy rysunek ilustruje ten pomysł.

wprowadź opis obrazu tutaj


0

FYI: Niedawno miałem problemy z próbą pobrania łatki z Github i umieszczenia jej w pliku lokalnym (co było „przesłonięciem” w nowej lokalizacji).

git amteż nie zastosowałby poprawki, ponieważ plik był „nie w indeksie” lub „brudny”. Ale odkryłem, że proste patchpolecenie może zastosować poprawkę. Zapytał mnie o nazwę pliku do załatania.

W każdym razie wykonałem swoją pracę ...

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.