Частично вишневый коммит с Git

Я работаю над двумя разными ветками: релиз и разработка.

Я заметил, что мне все еще нужно интегрировать некоторые изменения, внесенные в ветку release, обратно в ветку development.

Проблема в том, что мне не нужны все коммиты, только некоторые фрагменты в определенных файлах, поэтому простой

git cherry-pick bc66559

не делает трюк.

Когда я делаю

git show bc66559

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

Ответ 1

Основное, что вам нужно, это git add -p (-p является синонимом --patch). Это обеспечивает интерактивный способ проверки содержимого, позволяя вам решить, должен ли идти каждый хоккей, и даже позволить вам вручную отредактировать патч, если это необходимо.

Чтобы использовать его в сочетании с вишневым выбором:

git cherry-pick -n <commit> # get your patch, but don't commit (-n = --no-commit)
git reset                   # unstage the changes from the cherry-picked commit
git add -p                  # make all your choices (add the changes you do want)
git commit                  # make the commit!

(Спасибо Тиму Хенигану за то, что он напомнил мне, что git -cherry-pick имеет опцию -no-commit, и благодаря Феликс Рабе за то, что вам нужно reset! Если вы хотите просто уйти несколько вещей из коммита, вы можете использовать git reset <path>... для того, чтобы просто отключить эти файлы.)

Вы можете, конечно, указать конкретные пути к add -p, если это необходимо. Если вы начинаете с патча, вы можете заменить cherry-pick на apply.


Если вы действительно хотите git cherry-pick -p <commit> (этот параметр не существует), вы можете использовать

git checkout -p <commit>

Это будет отличать текущую фиксацию от комманды, которую вы укажете, и разрешить вам применять ханки из этой разницы по отдельности. Этот параметр может быть более полезен, если у фиксации, которую вы пытаетесь найти, есть конфликты слияния в части коммита, который вам неинтересен. (Обратите внимание, однако, что checkout отличается от cherry-pick: checkout пытается применить <commit> содержимое полностью, cherry-pick применяет diff от указанной фиксации от родителя. Это означает, что checkout может применять больше, чем только это commit, что может быть больше, чем вы хотите.)

Ответ 3

Предполагая, что изменения, которые вы хотите, находятся во главе ветки, из которой вы хотите внести изменения, используйте git checkout

для одного файла:

git checkout branch_that_has_the_changes_you_want path/to/file.rb

для нескольких файлов только цепочка:

git checkout branch_that_has_the_changes_you_want path/to/file.rb path/to/other_file.rb

Ответ 4

На основе Mike Monkiewicz ответьте, что вы также можете указать один или несколько файлов для проверки из поставляемого sha1/branch.

git checkout -p bc66559 -- path/to/file.java 

Это позволит вам интерактивно выбирать изменения, которые вы хотите применить к текущей версии файла.

Ответ 5

Если вы хотите указать список файлов в командной строке и выполнить все это одной атомарной командой, попробуйте:

git apply --3way <(git show -- list-of-files)

--3way: Если патч не применяется корректно, Git создаст конфликт слияния, чтобы вы могли запустить git mergetool. Пропуск --3way заставит Git отказаться от патчей, которые не применяются чисто.

Ответ 6

Если "частично вишня" означает "в файлах, выбирая некоторые изменения, но отбрасывая другие", это можно сделать, введя git stash:

  1. Сделайте полный выбор вишни.
  2. git reset HEAD^, чтобы преобразовать весь выбранный вишневый коммит в неустановленные рабочие изменения.
  3. Теперь git stash save --patch: интерактивно выбирайте нежелательный материал для хранения.
  4. Git откатывает спрятанные изменения из вашей рабочей копии.
  5. git commit
  6. Выбросьте stash нежелательных изменений: git stash drop.

Подсказка: если вы дадите имя stashу нежелательных изменений: git stash save --patch junk, то если вы забудете выполнить (6) сейчас, позже вы узнаете, что это за stash.