Jak zastosować łatkę git z jednego repozytorium do drugiego?


80

Mam dwa repozytoria, jedno jest głównym repozytorium dla biblioteki, a drugie to projekt korzystający z tej biblioteki.

Jeśli naprawię w podległym projekcie, chciałbym mieć łatwy sposób na zastosowanie tej poprawki z powrotem w górę.

Lokalizacja pliku jest inna w każdym repozytorium.

  • Główne repozytorium: www.playdar.org/static/playdar.js
  • Projekt: playlick.com/lib/playdar.js

Próbowałem użyć git format-patch -- lib/playdar.jsw projekcie listy odtwarzania, a następnie git amw głównym repozytorium playdar, ale różne lokalizacje plików w pliku poprawki powodowały błąd.

Czy istnieje łatwy sposób na zastosowanie łatki z danego zatwierdzenia w danym pliku do innego dowolnego pliku w innym miejscu?

Jeśli chodzi o punkty bonusowe, co jeśli plik, do którego chcesz zastosować poprawkę, nie znajduje się w repozytorium git?


Odpowiedzi:


117

Jeśli ręcznie edytując plik Patch jest wykluczone lub niewykonalne, można to zrobić za pomocą standardowych opcji (dostępne w git apply, git format-patchi GNU patch).

  1. -p<n>usuwa nwiodące katalogi ze ścieżek w łatce.

  2. Po przetworzeniu -p, --directory=<root>poprzedza rootdo każdej ścieżki w plastra przed zastosowaniem.

Przykład

Tak więc, na przykład, aby pobrać poprawkę, która była pierwotnie włączona static/playdar.jsi zastosować ją lib/playdar.js, uruchomisz:

$ cat patch_file | git am     \ 
          -p1                 \ # remove 1 leading directory ('static/')
         --directory='lib/'     # prepend 'lib/'

1
Czy jest jakaś szansa, aby znaleźć tę najlepszą odpowiedź? Jest to o wiele łatwiejsze niż ręczna edycja pliku poprawki.
weston

Jasne, jest to lepsza / łatwiejsza odpowiedź, chociaż odpowiedź @ araqnid jest nadal dobra.
James Wheare

Istotne dla dostosowania katalogu po pierwszej próbie bez --directory: stackoverflow.com/questions/24121709/ ...
Ioannis Filippidis

38

Łatka utworzona przez git format-patchjest po prostu plikiem tekstowym - możesz edytować nagłówki różnic, tak aby modyfikowały inną ścieżkę.

Na przykład dałoby to coś takiego:

diff --git a/lib/playdar.js b/lib/playdar.js
index 1234567..89abcde
-- a/lib/playdar.js
++ b/lib/playdar.js

Wszystko co musisz zrobić, to zmiana lib/playdar.jsna static/playdar.jsa następnie uruchom patcha przezgit am"

Plaster powinien być odczytywany przez standardowe narzędzia GNU poprawki dla ludzi, którzy nie mają git--- ale nie działają format-patchz -M, -Citp opcji do produkcji plastrów przemianowania w tym przypadku, ponieważ wsparcie dla nich nie jest uniwersalna.


1
Wrócimy później na tę stronę… To lepsza odpowiedź na zadane pytanie niż poprzedni „zwycięzca”, który zasugerował moduły podrzędne.
James Wheare

4

Zakładając, że oba projekty są projektami git, wygląda na to, że submoduły byłyby dla Ciebie idealne. Pozwala to projektowi git dynamicznie łączyć się z innym projektem git, zasadniczo wypalając repozytorium git bezpośrednio w innym repozytorium git, oba mają własne, odrębne życie.

Innymi słowy, dodaj „repozytorium główne” jako moduł podrzędny w „projekcie”. Za każdym razem, gdy zatwierdzasz / wysyłasz nowe rzeczy w „głównym repozytorium”, po prostu umieszczasz git pullje z powrotem w „projekcie”.


Hmm, po przeczytaniu dokumentacji modułu podrzędnego nie brzmi to jak „łatwy sposób”, chociaż może być najbardziej solidny. Wygląda na to, że będę musiał stworzyć submodule zawierający tylko playdar.jsplik następnie m.in., że w obu pozostałych projektów (nie chcę od wszystkiego innego www.playdar.orgw playlick.comprojekcie) może po prostu uciec się do ręcznego edytowania plików patch do teraz, aby być uczciwym . Lub kontynuuj kopiowanie wklejania między nimi. Twoje zdrowie.
James Wheare

Oto jasny i dokładny samouczek oraz wprowadzenie do modułu podrzędnego
James Wheare

2

Uzupełnienie odpowiedzi Henrika i zdobycie dodatkowego punktu

co jeśli plik, do którego chcesz zastosować poprawkę, nie znajduje się w repozytorium git?

Jeśli masz dostęp do katalogów pliku kandydata na łatkę pochodzącego z repozytorium git, możesz najpierw przekształcić to drzewo katalogów / plików w samo repozytorium git! (' git init': repozytorium git to po prostu .git w katalogu głównym).
Następnie ustawisz to repozytorium jako podmoduł dla swojego głównego projektu.


2

Użycie --relativeopcji format-patchmoże poprawić abstrakcję (ukryć nieistotne szczegóły repozytorium, z którego łatka została wygenerowana).

[repository-with-changes]
git format-patch --relative=(path-to-library) (base-commit-for-patch) ## 'HEAD~1'

Znalazłem --3wayopcję, która jest wymagana podczas nakładania łatki (aby uniknąć does not exist in indexbłędu) - Twój przebieg może się różnić. Użycie --directory=(...)jest prawdopodobnie konieczne tylko wtedy, gdy ścieżka docelowa nie jest katalogiem głównym repozytorium.

[repository-to-update]
git am --3way --directory=(path-to-library) (patch-file)

  • format-patch utworzy jeden plik łatki na każde zatwierdzenie do bieżącej gałęzi od 'base'.

  • --relativeWydaje się, że w niektórych przypadkach brakuje dokumentacji tej opcji , ale wydaje się, że i tak działa (od wersji 2.7.4).



1

Możesz po prostu tymczasowo usunąć (zmienić nazwę) główne repozytorium.

cd to/main/project
mv .git .git_
cd to/sub/project
git apply patchname
cd -
mv .git_ .git

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.