Как объединить определенные файлы из веток Git

У меня есть 2 филиала git branch1 и branch2, и я хочу объединить file.py в branch2 в file.py в branch1 и только этот файл.

По сути, я просто хочу работать с file.py в branch1, но хочу воспользоваться командой merge. Каков наилучший способ сделать это?

16 ответов

Решение

В принятом ответе уже упоминается использование git checkout, Теперь может быть содержание в file.py от branch2 что больше не применимо в branch1, Такая ситуация потребует выбора некоторых изменений и оставления других. Поэтому, чтобы получить полный контроль, выполните интерактивное слияние, используя --patch переключатель:

$ git checkout --patch branch2 file.py

Раздел интерактивного режима на странице руководства для 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

Команда split особенно полезна.

Как указано в комментариях, технически это не "слияние", поэтому в приведенной ниже ссылке используются кавычки. Однако мне редко нужно что-либо настолько сложное, как описывают другие авторы, поэтому я думаю, что это полезно, если не является правильным решением вопроса ОП.

Проверьте эту страницу: Git Подсказка: как "объединить" определенные файлы из другой ветки Это обеспечивает самый простой способ сделать это, IMHO.

В основном, чтобы применить это к вашей ситуации:

$ git checkout branch1 # i.e. make sure you're in branch1
$ git checkout branch2 file.py

Легко peasy, file.py теперь в branch1.

Ни один из других текущих ответов на самом деле не "объединит" файлы, как если бы вы использовали команду слияния. (В лучшем случае они потребуют от вас выбора различий вручную.) Если вы действительно хотите воспользоваться преимуществами объединения с использованием информации от общего предка, вы можете выполнить процедуру, основанную на процедуре, описанной в разделе "Расширенное объединение" в git. Справочное руководство.

Для этого протокола я предполагаю, что вы хотите объединить файл 'path / to / file.txt' из origin / master в 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

Есть все модификации для 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

Git checkout предоставляет--mergeвариант для этого

git checkout --merge branch2 file.py

С этой опцией конфликтующее слияние создается заново.

В противном случае, когда вместо этого должно произойти новое слияние:

      # Detach and overwrite file.py with content from branch2 
git checkout --detach
git checkout branch2 file.py

# Amend changes and switch back
git commit --amend --no-edit
git checkout -

# Merge the detached branch back in
git merge --no-commit -

Решение, которое я нашел, доставило мне меньше всего головной боли:

git checkout <b1>
git checkout -b dummy
git merge <b2>
git checkout <b1>
git checkout dummy <path to file>

После этого файл в path to file в b2 это то, что будет после полного слияния с b1.

Вы можете stash а также stash pop файл:

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

Объединить только изменения из Branch2 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' оформить заказ, если деревья достаточно разные.

Обратите внимание, что из-за этого Branch1 будет выглядеть так, как будто все в истории Branch2 к этому моменту было объединено, что может не соответствовать вашим ожиданиям. Лучшая версия первой проверки выше, вероятно,

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

в этом случае сообщение коммита, вероятно, также должно быть

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

Самое простое решение:

git checkout имя исходной ветки и пути к конкретным файлам, которые мы хотим добавить в нашу текущую ветку

git checkout sourceBranchName pathToFile

Я нахожу некоторые ответы полезными, но сбивающими с толку, чтобы избежать путаницы в будущем. Я пытаюсь помочь всем, у кого такая же путаница.

Я не буду использовать именаbranch1иbranch2, но (живой код) и (извлеченный из ) и ветка.

Теперь я хочу объединить некоторые определенные файлы из в , потому что слияние непосредственно изtestingилиstagingфилиалы не рекомендуется. Для этого я сделаю следующее:

  1. git checkout hotfix/abc
  2. git checkout --merge testing path/to/file1.php path/to/file2.js
  3. git add .
  4. git commit -m "Fixed specific issue"
  5. git push
  6. Теперь перейдите в репозиторий и сделайте запрос на ветку. Если вы не знаете, как это сделать, у меня есть небольшой урок по этому поводу. И если вы вообще хотите узнать, как работают эти ветки и git, я бы порекомендовал вам посмотреть это<=двадцатиминутный плейлист .
  7. Теперь просмотрите свойpull requestс иmergeэто. Если вы видите какие-либо конфликты, пришло время объединитьmasterвhotfix/abc. И разрешать конфликты там. А затем снова повторить шаг3-5с последующим7.

Я также получил помощь от справочного руководства .

Палец вверх, если поможет. Удачного кодирования :)

Решение Мэтью Тернера является самым простым, но выдает ошибку, если имя ветви1 и файл совпадает. В этом случае замените вторую строку на

git checkout branch2 -- file.py

Если git checkout --patch branch2 file.pyбудет принят, тогда я должен поделиться тем, что мы также можем использовать:

      git difftool <branch> [-- <file>]

( []значит необязательный)

Если сконфигурировано для diff.tool, объединить такие инструменты, как meldпозволит вам вручную объединить два файла с помощью графического интерфейса.

Одним из недостатков является то, что он не сможет скопировать или удалить файл, если он не существует в одной из ветвей. В таком случае нам необходимо git checkout branch2 -- file.py.

git difftoolтакже не хранит историю.

Если вас интересует только разрешение конфликтов, а не сохранение истории фиксации, следующий метод должен работать. Скажи, что хочешь слитьсяa.py b.py из BRANCHA в BRANCHB. Во-первых, убедитесь, что вBRANCHBлибо зафиксированы, либо спрятаны, а неотслеживаемые файлы отсутствуют. Затем:

git checkout BRANCHB
git merge BRANCHA
# 'Accept' all changes
git add .
# Clear staging area
git reset HEAD -- .
# Stash only the files you want to keep
git stash push a.py b.py
# Remove all other changes
git add .
git reset --hard
# Now, pull the changes
git stash pop

git не узнает, что есть конфликты в a.py b.py, но маркеры конфликта слияния присутствуют, если действительно конфликты были. Используя сторонний инструмент слияния, такой как VSCode, можно будет более комфортно разрешать конфликты.

Git переносит определенный файл из одной ветки в другую:

      git checkout --merge SourceBranch “path/to/file/fileToMigrate.java”

Пример упражнения:

Создайте ветки упражнений:

      git branch SourceBranch
git branch DestinationBranch

проверьте SourceBranch:

      git switch SourceBranch

Создайте 2 файла. Один для миграции, другой не для миграции:

  • создайте файлы «a.java» и «b.java»

извлеките целевую ветку и перенесите нужный файл из исходной ветки:

      git switch DestinationBranch
git checkout --merge SourceBranch “path/to/file/a.java”

На этом этапе «a.java» объединяется с DestinationBranch, а «b.java» не объединяется (как предполагалось).

В DestinationBranch продолжайте как обычно, например:

  • если вновь объединенный файл «a.java» не подготовлен, то:git add .
  • если это постановка, то:git commit -m “Merged: a.java”

То, что я сделал, немного вручную, но я:

  1. Слил ветки нормально; Отменил слияние сrevert;
  2. Проверил все мои файлы в HEAD~1, то есть их состояние в фиксации слияния;
  3. Обновил мои коммиты, чтобы скрыть этот взлом из истории коммитов.

Некрасиво? Да. Легко запомнить? Также да.

Я нахожусь в той же ситуации, я хочу объединить файл из ветки, в которой много коммитов на 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
Другие вопросы по тегам