Як об'єднати конкретні файли з гілок Git


179

У мене є 2 гілки гілки branch1 і branch2, і я хочу об'єднати file.py в branch2 в file.py в branch1 і тільки цей файл.

По суті, я просто хочу працювати над file.py у branch1, але хочу скористатися командою злиття. Який найкращий спосіб зробити це?



Відповіді:


207

Коли вміст перебуває file.pyз галузі branch2, що більше не застосовується до гілки1 , потрібно вибрати деякі зміни та залишити інші. Для повного контролю зробіть інтерактивне злиття за допомогою --patchперемикача:

$ git checkout --patch branch2 file.py

У розділі інтерактивного режиму на сторінці man git-add(1)пояснюються ключі, які слід використовувати:

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

Особливо корисна команда розділення.


3
Як ми можемо використовувати патч і одночасно використовувати інструмент злиття? замість ключового матеріалу
Габріель

@Gabriel Я використовував Git навіть із файлами патчів та тарболами, тому що так легко створити репо ( git init <dir>) і остаточно викинути його ( rm -r <dir>).
pdp

105

Хоча це не є злиттям саме по собі, іноді потрібен весь вміст іншого файлу на іншій гілці. Повідомлення в блозі Джейсона Рудольфа надає простий спосіб копіювання файлів з однієї гілки в іншу. Застосовуйте техніку наступним чином:

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

Зараз file.pyзараз у відділенні1 .


91
Легко, але це насправді не є злиття . Він просто переписує file.pyвсе, що є у галузі 2.
Грег Хьюгілл

Що робити, якщо ви з’єднаєте файл назад із відгалуження1 до гілки2? Ви отримаєте конфлікт!
Амір

Чи зберігає це історію фіксації?
C2H50H

18

Жоден з інших поточних відповідей насправді не "злиє" файли, як якщо б ви використовували команду "об'єднання". (У кращому випадку вони вимагають, щоб ви вручну вибирали різниці.) Якщо ви дійсно хочете скористатися злиттям, використовуючи інформацію від загального предка, ви можете дотримуватися процедури, заснованої на одній, знайденій у розділі "Розширене злиття" в git Довідковий посібник.

Для цього протоколу я припускаю, що ви хочете об'єднати файл 'path / to / file.txt' від початкового / головного до HEAD - змінити відповідно. (Не потрібно знаходитись у верхній папці вашого сховища, але це допомагає.)

# 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 повинен використовувати всі налаштування злиття за замовчуванням для форматування тощо.

Також зауважте, що якщо ваша "наша" є версією робочої копії, і ви не хочете бути дуже обережними, ви можете працювати безпосередньо з файлом:

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

15

Є чи все модифікації file.pyв branch2в своїх фіксаціях, окремо від змін в інші файли? Якщо так, ви можете просто cherry-pickзмінити:

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

В іншому випадку, mergeне працює над індивідуальними шляхами ... Ви можете також просто створити git diffпатч file.pyзмін від branch2і git applyїх до branch1:

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

8

Ви можете stashі stash popфайл:

git checkout branch1
git checkout branch2 file.py
git stash
git checkout branch1
git stash pop

Це замінює branch1 / file.py із вмістом bran2 / file.py замість злиття, яке повинно викликати конфлікт злиття для вирішення.
plumSemPy

2

Щоб об'єднати лише зміни, пов'язані з відгалуженнями2, виконайте file.pyінші зміни.

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

Злиття ніколи не перегляне жоден інший файл. Можливо, вам знадобиться "-f" на касах, якщо дерева досить різні.

Зауважте, що це дозволить вести1, виглядаючи так, ніби все в історії галузі2 до цього моменту було злито, що може бути не тим, що ви хочете. Напевно, краща версія першого замовлення вище

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

в такому випадку, можливо, також повинно бути повідомлення про фіксацію

git commit -m"merging only $(git rev-parse branch2):file.py into branch1"

0

Я в такій же ситуації, я хочу об'єднати файл із гілки, яка має багато комітів на ньому на 2 гілці. Я перепробував багато способів, описаних вище, та інших, які я виявив в Інтернеті, і все не вдалося (оскільки історія фіксації є складною), тому я вирішу зробити свій шлях (божевільний шлях).

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

0

Що я зробив, це трохи посібник, але я:

  1. З’єднуються гілки нормально; Відмінено злиття з revert;
  2. Перевірив усі мої файли HEAD~1, тобто їх стан у комісії злиття;
  3. Скинув мої зобов’язання, щоб сховати цей хакер з історії комісій.

Потворний? Так. Легко запам’ятати? Також так.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.