Частично выбираем коммит с помощью Git
-
20-09-2019 - |
Вопрос
Я работаю над 2 разными ветвями: освобождение и развитие.
Я заметил, что мне все еще нужно интегрировать некоторые изменения, которые были внесены в освобождение ответвляться обратно в развитие филиал.
Проблема в том, что мне не нужен весь коммит, только некоторые фрагменты в определенных файлах, поэтому простой
git cherry-pick bc66559
не делает нужного эффекта.
Когда я делаю
git show bc66559
Я вижу разницу, но на самом деле не знаю хорошего способа применить это частично к моему текущему рабочему дереву.
Решение
Основная вещь, которую вы захотите здесь получить, это 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 , и спасибо Феликсу Рабе за указание на то, что вам нужно выполнить сброс!Если вы хотите исключить из коммита только несколько вещей, вы могли бы использовать git reset <path>...
чтобы удалить только эти файлы.)
Конечно, вы можете указать конкретные пути к add -p
при необходимости.Если вы начинаете с патча, вы могли бы заменить cherry-pick
с apply
.
Если вы действительно хотите git cherry-pick -p <commit>
(эта опция не существует), вы можете использовать
git checkout -p <commit>
Это будет отличать текущий коммит от указанного вами коммита и позволит вам применять фрагменты из этого diff по отдельности.Этот параметр может быть более полезным, если в коммите, который вы извлекаете, есть конфликты слияния в части коммита, которая вас не интересует.(Заметим, однако, что checkout
отличается от cherry-pick
: checkout
пытается применить <commit>
содержимое полностью, cherry-pick
применяет diff указанного коммита к его родительскому элементу.Это означает , что checkout
можете применить больше, чем просто этот коммит, который может быть больше, чем вы хотите.)
Другие советы
Я знаю, что отвечаю на старый вопрос, но, похоже, есть новый способ сделать это с помощью интерактивной проверки:
git checkout -p bc66559
Кредит для Могу ли я интерактивно выбирать фрагменты из другого коммита git?
Предполагая, что изменения, которые вы хотите внести, находятся в начале ветки, из которой вы хотите внести изменения, используйте 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
Опираясь на Майк Монкевич ответ вы также можете указать один или несколько файлов для извлечения из предоставленного sha1 / branch.
git checkout -p bc66559 -- path/to/file.java
Это позволит вам в интерактивном режиме выбрать изменения, которые вы хотите применить к вашей текущей версии файла.
Если вы хотите указать список файлов в командной строке и выполнить все это одной элементарной командой, попробуйте:
git apply --3way <(git show -- list-of-files)
--3way
:Если исправление не применяется чисто, Git создаст конфликт слияния, чтобы вы могли запустить git mergetool
.Опуская --3way
заставит Git отказаться от исправлений, которые не применяются чисто.
Если "частичный выбор вишни" означает "внутри файлов, выбирая некоторые изменения, но отбрасывая другие", это можно сделать, введя git stash
:
- Сделайте полный сбор вишни.
git reset HEAD^
чтобы преобразовать весь выбранный коммит в неустановленные рабочие изменения.- Сейчас
git stash save --patch
:интерактивно выберите ненужный материал для хранения. - Git откатывает сохраненные изменения из вашей рабочей копии.
git commit
- Выбросьте запас нежелательных изменений:
git stash drop
.
Совет:если вы дадите тайнику с нежелательными изменениями имя: git stash save --patch junk
тогда, если вы забудете выполнить (6) сейчас, позже вы узнаете тайник таким, какой он есть.