Jak scalić określone pliki z gałęzi Git

179

Mam 2 gałęzie git branch1 i branch2 i chcę scalić plik.py w gałęzi2 do pliku.py w gałęzi1 i tylko ten plik.

Zasadniczo chcę po prostu popracować nad plikiem file.py w branch1, ale chcę skorzystać z polecenia merge. Jaki jest najlepszy sposób, aby to zrobić?

rwolst
źródło

Odpowiedzi:

207

Gdy treść pochodzi file.pyz gałęzi 2, która nie ma już zastosowania do gałęzi 1 , wymaga wybrania niektórych zmian i pozostawienia innych. Aby uzyskać pełną kontrolę, wykonaj interaktywne scalanie za pomocą --patchprzełącznika:

$ git checkout --patch branch2 file.py

Sekcja trybu interaktywnego na stronie podręcznika zawiera git-add(1)wyjaśnienia klawiszy, które mają być używane:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help

Polecenie Split jest szczególnie przydatne.

pdp
źródło
3
Jak możemy korzystać z łatki i jednocześnie używać narzędzia do scalania? zamiast kluczowych rzeczy
Gabriel
@Gabriel Używałem Gita nawet z plikami łatek i tarballami, ponieważ tak łatwo jest utworzyć repozytorium ( git init <dir>) i ostatecznie go wyrzucić ( rm -r <dir>).
pdp
105

Chociaż samo w sobie nie jest to scalanie , czasami potrzebna jest cała zawartość innego pliku w innej gałęzi. Post na blogu Jasona Rudolpha zapewnia prosty sposób kopiowania plików z jednej gałęzi do drugiej. Zastosuj technikę w następujący sposób:

$ git checkout branch1 # ensure in branch1 is checked out and active
$ git checkout branch2 file.py

Teraz file.pyjest teraz w branch1 .

Matthew Turner
źródło
91
Łatwe, ale to nie jest właściwie połączenie . Po prostu nadpisuje file.pyto, co jest w gałęzi 2.
Greg Hewgill
Co się stanie, jeśli z powrotem scalisz plik z gałęzi 1 do gałęzi 2? Pojawi się konflikt!
Amir,
Czy to zachowuje historię zmian?
C2H50H
18

Żadna z innych bieżących odpowiedzi nie „scali” plików, tak jakbyś używał polecenia scalania. (W najlepszym przypadku będą wymagały ręcznego wybierania różnic). Jeśli faktycznie chcesz skorzystać z połączenia przy użyciu informacji od wspólnego przodka, możesz wykonać procedurę opartą na procedurze znajdującej się w sekcji „Zaawansowane scalanie” gita Instrukcja obsługi.

W przypadku tego protokołu zakładam, że chcesz scalić plik „ścieżka / do / plik.txt” od źródła / wzorca do pliku HEAD - odpowiednio zmodyfikuj. (Nie musisz znajdować się w głównym katalogu repozytorium, ale to pomaga.)

# Find the merge base SHA1 (the common ancestor) for the two commits:
git merge-base HEAD origin/master

# Get the contents of the files at each stage
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show HEAD:path/to/file.txt > ./file.ours.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt

# You can pre-edit any of the files (e.g. run a formatter on it), if you want.

# Merge the files
git merge-file -p ./file.ours.txt ./file.common.txt ./file.theirs.txt > ./file.merged.txt

# Resolve merge conflicts in ./file.merged.txt
# Copy the merged version to the destination
# Clean up the intermediate files

git merge-file powinien używać wszystkich domyślnych ustawień scalania do formatowania i tym podobnych.

Pamiętaj również, że jeśli Twoja „nasza” jest wersją roboczą i nie chcesz być zbyt ostrożny, możesz operować bezpośrednio na pliku:

git merge-base HEAD origin/master
git show <merge-base SHA1>:path/to/file.txt > ./file.common.txt
git show origin/master:path/to/file.txt > ./file.theirs.txt
git merge-file path/to/file.txt ./file.common.txt ./file.theirs.txt
RM
źródło
15

Czy wszystkie modyfikacje file.pyw branch2swoich własnych zatwierdzeń, niezależnie od zmian do innych plików? Jeśli tak, możesz po prostu cherry-pickzmienić:

git checkout branch1
git cherry-pick <commit-with-changes-to-file.py>

W przeciwnym razie, mergenie działa na poszczególne ścieżki ... równie dobrze można po prostu stworzyć git diffskrawek file.pyzmian od branch2i git applyim branch1:

git checkout branch2
git diff <base-commit-before-changes-to-file.py> -- file.py > my.patch
git checkout branch1
git apply my.patch

źródło
8

Możesz stashi stash popplik:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop
Martin G.
źródło
Spowoduje to nadpisanie branch1 / file.py zawartością branch2 / file.py zamiast scalania, które powinno wywołać konflikt scalania do rozwiązania.
plumSemPy
2

Aby scalić tylko zmiany z branch2, usuń file.pypozostałe zmiany.

git checkout -B wip branch2
git read-tree branch1
git checkout branch2 file.py
git commit -m'merging only file.py history from branch2 into branch1'
git checkout branch1
git merge wip

Funkcja Merge nigdy nie obejrzy żadnego innego pliku. Być może będziesz musiał '-f' przy kasach, jeśli drzewa są wystarczająco różne.

Zauważ, że to spowoduje, że gałąź1 będzie wyglądać tak, jakby wszystko w historii branch2 do tego momentu zostało scalone, co może nie być tym, czego chcesz. Prawdopodobnie jest lepsza wersja pierwszej kasy powyżej

git checkout -B wip `git merge-base branch1 branch2`

w takim przypadku komunikat o zatwierdzeniu powinien również być

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"
jthill
źródło
0

Jestem w tej samej sytuacji, chcę scalić plik z gałęzi, która ma wiele zatwierdzeń na gałęzi 2. Wypróbowałem wiele sposobów powyżej i innych, które znalazłem w Internecie i wszystkie zawiodły (ponieważ historia zatwierdzania jest złożona), więc postanawiam zrobić wszystko po swojemu (szalony sposób).

git merge <other-branch>
cp file-to-merge file-to-merge.example
git reset --hard HEAD (or HEAD^1 if no conflicts happen)
cp file-to-merge.example file-to-merge
Trac Nguyen
źródło
0

To, co zrobiłem, jest trochę ręczne, ale:

  1. Łączyłem gałęzie normalnie; Cofnięto scalanie z revert;
  2. Wyewidencjonowałem wszystkie moje pliki do HEAD~1, to znaczy ich stan w zatwierdzeniu scalenia;
  3. Ponownie usunąłem moje zobowiązania, aby ukryć ten hacking w historii zmian.

Brzydki? Tak. Łatwe do zapamiętania? Też tak.

Lucas Lima
źródło