Как выборочно объединить или выбрать изменения из другой ветки в Git?
Я использую git для нового проекта, который имеет две параллельные - но в настоящее время экспериментальные - ветви разработки:
master
: импорт существующей кодовой базы плюс несколько модов, в которых я обычно уверенexp1
: экспериментальный филиал № 1exp2
: экспериментальный филиал № 2
exp1
а также exp2
представляют два очень разных архитектурных подхода. Пока я не продвинусь дальше, у меня нет никакого способа узнать, какой из них (если любой) будет работать. Поскольку я делаю успехи в одной ветви, у меня иногда есть изменения, которые были бы полезны в другой ветви и хотели бы объединить только те.
Каков наилучший способ объединения выборочных изменений из одной ветви разработки в другую, оставляя после себя все остальное?
Подходы, которые я рассмотрел:
git merge --no-commit
с последующей ручной постановкой большого количества правок, которые я не хочу делать общими между ветвями.Ручное копирование общих файлов во временный каталог с последующим
git checkout
перейти к другой ветке и затем вручную скопировать ее из временного каталога в рабочее дерево.Вариация на выше. Отказаться от
exp
пока что разветвляются и используют два дополнительных локальных репозитория для экспериментов. Это делает ручное копирование файлов намного проще.
Все три из этих подходов кажутся утомительными и подверженными ошибкам. Я надеюсь, что есть лучший подход; что-то похожее на параметр пути фильтра, который сделает git-merge
более избирательно
29 ответов
Вы используете команду cherry-pick для получения отдельных коммитов из одной ветви.
Если нужного вам изменения нет в отдельных фиксациях, то используйте метод, показанный здесь, чтобы разделить фиксацию на отдельные фиксации. Грубо говоря, вы используете git rebase -i
чтобы получить исходный коммит для редактирования, затем git reset HEAD^
выборочно отменить изменения, то git commit
совершить этот бит как новый коммит в истории.
В журнале Red Hat есть еще один замечательный метод, в котором они используют git add --patch
или возможно git add --interactive
который позволяет вам добавлять только части фрагмента, если вы хотите разделить различные изменения в отдельном файле (поиск на этой странице для "разделения").
Разделив изменения, теперь вы можете выбрать те, которые хотите.
У меня была точно такая же проблема, как вы упомянули выше. Но я нашел это более ясным в объяснении ответа.
Резюме:
Извлечь путь (и) из ветви, которую вы хотите объединить,
$ git checkout source_branch -- <paths>...
Подсказка: это также работает без
--
как видно в связанном посте.или выборочно объединить куски
$ git checkout -p source_branch -- <paths>...
Или используйте сброс, а затем добавьте с опцией
-p
,$ git reset <paths>... $ git add -p <paths>...
Наконец совершить
$ git commit -m "'Merge' these changes"
Чтобы выборочно объединить файлы из одной ветви в другую, запустите
git merge --no-ff --no-commit branchX
где branchX
ветвь, с которой вы хотите объединиться в текущую ветку.
--no-commit
Опция установит файлы, которые были объединены Git, без их фиксации. Это даст вам возможность модифицировать объединенные файлы так, как вы хотите, а затем зафиксировать их самостоятельно.
В зависимости от того, как вы хотите объединить файлы, есть четыре случая:
1) Вы хотите истинное слияние.
В этом случае вы принимаете объединенные файлы так, как Git автоматически объединяет их, а затем фиксируете их.
2) Есть файлы, которые вы не хотите объединять.
Например, вы хотите сохранить версию в текущей ветви и игнорировать версию в ветви, из которой вы объединяете.
Чтобы выбрать версию в текущей ветке, запустите:
git checkout HEAD file1
Это восстановит версию file1
в текущей ветке и перезаписать file1
Автоматизирован Git.
3) Если вы хотите версию в BranchX (а не истинное слияние).
Бежать:
git checkout branchX file1
Это восстановит версию file1
в branchX
и перезаписать file1
автоматически объединен с Git.
4) Последний случай, если вы хотите выбрать только конкретные слияния в file1
,
В этом случае вы можете редактировать измененные file1
напрямую, обновите его до версии, которую вы хотите file1
стать, а затем совершить.
Если Git не может объединить файл автоматически, он сообщит о файле как о "без объединения " и создаст копию, в которой вам нужно будет разрешить конфликты вручную.
Чтобы объяснить далее на примере, скажем, вы хотите объединить branchX
в текущую ветку:
git merge --no-ff --no-commit branchX
Затем вы запускаете git status
Команда для просмотра статуса измененных файлов.
Например:
git status
# On branch master
# Changes to be committed:
#
# modified: file1
# modified: file2
# modified: file3
# Unmerged paths:
# (use "git add/rm <file>..." as appropriate to mark resolution)
#
# both modified: file4
#
куда file1
, file2
, а также file3
файлы, которые git успешно слил, автоматически
Это означает, что изменения в master
а также branchX
для всех этих трех файлов были объединены без каких-либо конфликтов.
Вы можете проверить, как слияние было сделано, запустив git diff --cached
;
git diff --cached file1
git diff --cached file2
git diff --cached file3
Если вы обнаружите, что слияние нежелательно, вы можете
- редактировать файл напрямую
- спасти
git commit
Если вы не хотите объединяться file1
и хотите сохранить версию в текущей ветке
Бежать
git checkout HEAD file1
Если вы не хотите объединяться file2
и только хочу версию в branchX
Бежать
git checkout branchX file2
Если ты хочешь file3
быть объединенным автоматически, ничего не делать.
Git уже слил это на данный момент.
file4
выше - неудачное слияние Git. Это означает, что изменения в обеих ветвях происходят в одной строке. Здесь вам нужно будет разрешить конфликты вручную. Вы можете отменить объединение, выполнив непосредственное редактирование файла или выполнив команду checkout для версии в нужной ветке. file4
становиться.
Наконец, не забудьте git commit
,
Мне не нравятся вышеуказанные подходы. Использование cherry-pick отлично подходит для выбора одного изменения, но это неприятно, если вы хотите внести все изменения, кроме некоторых плохих. Вот мой подход.
Здесь нет --interactive
аргумент, который вы можете передать git merge.
Вот альтернатива:
У вас есть некоторые изменения в ветке 'feature', и вы хотите, чтобы некоторые, но не все, перешли к 'master' не небрежным образом (т.е. вы не хотите выбирать и фиксировать каждую из них)
git checkout feature
git checkout -b temp
git rebase -i master
# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change
# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
git checkout master
git pull . temp
git branch -d temp
Так что просто оберните это в сценарии оболочки, измените master на $ to и измените функцию на $ from, и все готово:
#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp
Есть еще один путь:
git checkout -p
Это смесь между git checkout
а также git add -p
и вполне может быть именно то, что вы ищете:
-p, --patch
Interactively select hunks in the difference between the <tree-ish>
(or the index, if unspecified) and the working tree. The chosen
hunks are then applied in reverse to the working tree (and if a
<tree-ish> was specified, the index).
This means that you can use git checkout -p to selectively discard
edits from your current working tree. See the “Interactive Mode”
section of git-add(1) to learn how to operate the --patch mode.
Хотя некоторые из этих ответов довольно хороши, мне кажется, что никто не ответил на первоначальное ограничение OP: выбор определенных файлов из определенных веток. Это решение делает это, но может быть утомительным, если есть много файлов.
Допустим, у вас есть master
, exp1
, а также exp2
ветви. Вы хотите объединить один файл из каждой экспериментальной ветви в мастер. Я бы сделал что-то вроде этого:
git checkout master
git checkout exp1 path/to/file_a
git checkout exp2 path/to/file_b
# save these files as a stash
git stash
# merge stash with master
git merge stash
Это даст вам различия в файлах для каждого файла, который вы хотите. Ничего более. Не меньше. Полезно, чтобы у вас были радикально отличающиеся изменения файлов между версиями - в моем случае, изменение приложения с Rails 2 на Rails 3.
РЕДАКТИРОВАТЬ: это объединит файлы, но делает умное объединение. Я не смог выяснить, как использовать этот метод для получения информации о различиях в файле (возможно, это все равно будет для экстремальных различий. Раздражающие мелочи, такие как пробелы, объединяются, если вы не используете -s recursive -X ignore-all-space
опция)
1800 ИНФОРМАЦИЯ ответ полностью правильный. Однако, как git noob, "использовать git cherry-pick" было недостаточно для того, чтобы я мог понять это, не копаясь в интернете, поэтому я решил опубликовать более подробное руководство на случай, если кто-то еще будет в похожая лодка.
Мой вариант использования - выборочная загрузка изменений из чьей-либо ветки github в мою. Если у вас уже есть локальный филиал с изменениями, вам нужно только выполнить шаги 2 и 5-7.
Создайте (если не создали) локальную ветвь с изменениями, которые вы хотите внести.
$ git branch mybranch <base branch>
Переключитесь на это.
$ git checkout mybranch
Внесите необходимые изменения из учетной записи другого человека. Если вы еще этого не сделали, вам нужно добавить их в качестве удаленного.
$ git remote add repos-w-changes <git url>
Сноси все с их ветки.
$ git pull repos-w-changes branch-i-want
Просмотрите журналы фиксации, чтобы увидеть, какие изменения вы хотите:
$ git log
Вернитесь к ветке, в которую хотите внести изменения.
$ git checkout originalbranch
Черри выбирает ваши коммиты, один за другим, с помощью хешей.
$ git cherry-pick -x hash-of-commit
Наконечник шляпы: http://www.sourcemage.org/Git_Guide
Вот как можно заменить Myclass.java
файл в master
ветвь с Myclass.java
в feature1
ветка. Это будет работать, даже если Myclass.java
не существует на master
,
git checkout master
git checkout feature1 Myclass.java
Обратите внимание, что это перезапишет, а не объединит, и скорее проигнорирует локальные изменения в основной ветке.
Простой способ - объединить конкретные файлы из двух веток, а не просто заменить конкретные файлы файлами из другой ветки.
Шаг первый: отличаться от ветвей
git diff branch_b > my_patch_file.patch
Создает файл патча разницы между текущей веткой и branch_b
Шаг второй: примените патч к файлам, соответствующим шаблону
git apply -p1 --include=pattern/matching/the/path/to/file/or/folder my_patch_file.patch
полезные заметки по опциям
Ты можешь использовать *
в качестве шаблона в шаблоне включения.
Косые черты не нужно избегать.
Кроме того, вместо этого вы можете использовать --exclude и применять его ко всем, кроме файлов, соответствующих шаблону, или отменить патч с помощью -R
Параметр -p1 является удержанием команды *unix patch и тот факт, что содержимое файла исправления предшествует каждому имени файла с a/
или же b/
(или более того, в зависимости от того, как был сгенерирован файл патча), который нужно удалить, чтобы он мог определить реальный файл и путь к файлу, к которому необходимо применить патч.
Проверьте страницу справочника для git-apply для большего количества вариантов.
Шаг третий: нет третьего шага
Очевидно, что вы захотите зафиксировать свои изменения, но кто скажет, что у вас нет других связанных твиков, которые вы хотели бы сделать, прежде чем сделать свой коммит.
Вот как вы можете заставить историю следовать только паре файлов из другой ветки с минимальными усилиями, даже если более "простое" объединение принесло бы гораздо больше изменений, которые вам не нужны.
Во-первых, вы сделаете необычный шаг, объявив заранее, что вы собираетесь зафиксировать слияние, без мерзавца, который вообще ничего не делает с файлами в вашем рабочем каталоге:
git merge --no-ff --no-commit -s ours branchname1
,,, где "branchname " - это то, из чего вы утверждаете, что объединяетесь. Если вы сделаете коммит сразу, он не внесет никаких изменений, но он все равно покажет родословную из другой ветви. Вы можете добавить больше веток / тегов / и т.д. в командной строке, если вам нужно, а также. На данный момент, однако, нет никаких изменений для фиксации, поэтому получите файлы из других ревизий, затем.
git checkout branchname1 -- file1 file2 etc
Если вы объединялись из более чем одной ветки, повторите при необходимости.
git checkout branchname2 -- file3 file4 etc
Теперь файлы из другой ветки находятся в индексе, готовые к фиксации, с историей.
git commit
и вы будете много объяснять, что делать в этом сообщении коммита.
Пожалуйста, обратите внимание, на случай, если неясно, что это неправильно. Это не в духе того, для чего нужна "ветка", и "вишня" - это более честный способ сделать то, что вы будете делать здесь. Если вы захотите сделать еще одно "слияние" для других файлов в той же ветке, которую вы не перенесли в прошлый раз, это остановит вас сообщением "уже в курсе". Это признак отсутствия ветвления, когда у нас должно быть, в ветке "from" должно быть несколько разных ветвей.
Самый простой способ - установить репо в ту ветку, с которой вы хотите объединиться, и затем запустить,
git checkout [branch with file] [path to file you would like to merge]
Если вы бежите
git status
вы увидите файл уже в постановке...
Тогда беги
git commit -m "Merge changes on '[branch]' to [file]"
Просто.
Я знаю, что немного опоздал, но это мой рабочий процесс объединения отдельных файлов.
#make a new branch ( this will be temporary)
git checkout -b newbranch
# grab the changes
git merge --no-commit featurebranch
# unstage those changes
git reset HEAD
(you can now see the files from the merge are unstaged)
# now you can chose which files are to be merged.
git add -p
# remember to "git add" any new files you wish to keep
git commit
Странно, что у git до сих пор нет такого удобного инструмента "из коробки". Я интенсивно использую его, когда обновляю ветку старой версии (в которой все еще много пользователей программного обеспечения) только некоторыми исправлениями из ветки текущей версии. В этом случае часто требуется быстро получить только несколько строк кода из файла в стволе, игнорируя множество других изменений (которые не должны входить в старую версию)... И, конечно, интерактивное трехстороннее объединение нужен в этом случае, git checkout --patch <branch> <file path>
не может использоваться для этой избирательной цели слияния.
Вы можете сделать это легко:
Просто добавьте эту строку в [alias]
раздел в вашем глобальном .gitconfig
или местный .git/config
файл:
[alias]
mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; /C/BCompare3/BCompare.exe $2.theirs $2 $2.base $2; rm -f $2.theirs; rm -f $2.base;' -"
Это означает, что вы используете Beyond Compare. Просто измените программное обеспечение на ваш выбор, если это необходимо. Или вы можете изменить его на трехстороннее автоматическое слияние, если вам не нужно интерактивное выборочное слияние:
[alias]
mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; git merge-file $2 $2.base $2.theirs; rm -f $2.theirs; rm -f $2.base;' -"
Тогда используйте как это:
git mergetool-file <source branch> <file path>
Это даст вам истинную выборочную возможность слияния в виде дерева любого файла в другой ветке.
Я нашел этот пост, чтобы содержать самый простой ответ. Просто сделайте:
$ #git checkout <branch from which you want files> <file paths>
Пример:
$ #pulling .gitignore file from branchB into current branch
$ git checkout branchB .gitignore
Смотрите пост для получения дополнительной информации.
У меня была точно такая же проблема, как вы упомянули выше. Но я нашел этот блог Git более четким в объяснении ответа.
Команда по вышеуказанной ссылке:
#You are in the branch you want to merge to
git checkout <branch_you_want_to_merge_from> <file_paths...>
Это не совсем то, что вы искали, но это было полезно для меня:
git checkout -p <branch> -- <paths> ...
Это смесь некоторых ответов.
Я бы сделал
git diff commit1..commit2 filepattern | git-apply --index && git commit
Таким образом, вы можете ограничить диапазон коммитов для файлового шаблона из ветви.
Похищен у: http://www.gelato.unsw.edu.au/archives/git/0701/37964.html
Как насчет git reset --soft branch
? Я удивлен, что никто еще не упомянул об этом.
Для меня это самый простой способ выборочно выбрать изменения из другой ветки, так как эта команда помещает в мое рабочее дерево все изменения различий, и я могу легко выбрать или вернуть то, что мне нужно. Таким образом, я имею полный контроль над зафиксированными файлами.
Мне нравится ответ 'git-interactive-merge' выше, но есть один более простой. Позвольте git сделать это для вас, используя интерактивную комбинацию ребаз и на:
A---C1---o---C2---o---o feature
/
----o---o---o---o master
Так что дело в том, что вы хотите, чтобы C1 и C2 находились в ответвлении "Feature" (точка ветвления "A"), но пока нет ни одного из остальных.
# git branch temp feature
# git checkout master
# git rebase -i --onto HEAD A temp
Который, как указано выше, перенаправляет вас в интерактивный редактор, где вы выбираете строки "выбора" для C1 и C2 (как указано выше). Сохраните и выйдите, а затем он продолжит ребазирование и даст вам ветку temp, а также HEAD на master + C1 + C2:
A---C1---o---C2---o---o feature
/
----o---o---o---o-master--C1---C2 [HEAD, temp]
Затем вы можете просто обновить master до HEAD и удалить временную ветку, и все готово:
# git branch -f master HEAD
# git branch -d temp
Ты можешь использовать read-tree
прочитать или объединить данное удаленное дерево в текущий индекс, например:
git remote add foo git@example.com/foo.git
git fetch foo
git read-tree --prefix=my-folder/ -u foo/master:trunk/their-folder
Чтобы выполнить слияние, используйте -m
вместо.
Смотрите также: Как мне объединить подкаталог в git?
Я знаю, что этот вопрос старый и есть много других ответов, но я написал свой собственный скрипт под названием "pmerge", чтобы частично объединить каталоги. Эта работа еще не завершена, и я все еще изучаю скрипты git и bash.
Эта команда использует git merge --no-commit
а затем отменяет изменения, которые не соответствуют указанному пути.
Использование: git pmerge branch path
Пример: git merge develop src/
Я не проверял это экстенсивно. В рабочем каталоге не должно быть никаких незафиксированных изменений и неотслеживаемых файлов.
#!/bin/bash
E_BADARGS=65
if [ $# -ne 2 ]
then
echo "Usage: `basename $0` branch path"
exit $E_BADARGS
fi
git merge $1 --no-commit
IFS=$'\n'
# list of changes due to merge | replace nulls w newlines | strip lines to just filenames | ensure lines are unique
for f in $(git status --porcelain -z -uno | tr '\000' '\n' | sed -e 's/^[[:graph:]][[:space:]]\{1,\}//' | uniq); do
[[ $f == $2* ]] && continue
if git reset $f >/dev/null 2>&1; then
# reset failed... file was previously unversioned
echo Deleting $f
rm $f
else
echo Reverting $f
git checkout -- $f >/dev/null 2>&1
fi
done
unset IFS
Простой подход для выборочного слияния / фиксации по файлу:
git checkout dstBranch
git merge srcBranch
// make changes, including resolving conflicts to single files
git add singleFile1 singleFile2
git commit -m "message specific to a few files"
git reset --hard # blow away uncommitted changes
Если у вас не так много файлов, которые были изменены, это оставит вас без дополнительных фиксаций.
1. Дублирующая ветка временно$ git checkout -b temp_branch
2. Сброс до последнего желаемого коммита$ git reset --hard HEAD~n
, где n
это количество коммитов, которые нужно вернуть
3. Оформите каждый файл из оригинальной ветки$ git checkout origin/original_branch filename.ext
Теперь вы можете зафиксировать и принудительно нажать (чтобы перезаписать удаленный), если это необходимо.
Я нашел решение этого вопроса, которое действительно красиво и просто. Поэтому я просто держу его здесь для себя и других, которые хотят использовать это решение.
ОТВЕТ
Допустим, я нахожусь в ветке 1 , которая содержит один файл, file1.txt
Теперь я хочу объединиться сfile1.txt
с другим файломfile2.txt
который находится в ветке2 .
Так что команда должна быть,
git checkout --patch branch2 <path_of_file2.txt_in_context_of_branch2>
который предлагает консоль сказать, что вам нужно ввести определенный символ, чтобы отразить изменения в вашей текущей ветке branch1 . Иногда я использую a , чтобы принять все куски.
Я надеюсь, что этот ответ будет полезен.
Спасибо
Если вам нужно только объединить определенный каталог и оставить все остальное без изменений, но при этом сохранить историю, вы можете попробовать это... создать новый target-branch
от master
прежде чем экспериментировать.
Шаги ниже предполагают, что у вас есть две ветви target-branch
а также source-branch
и каталог dir-to-merge
что вы хотите объединить в source-branch
, Также предположим, что у вас есть другие каталоги, такие как dir-to-retain
в цели, которую вы не хотите изменять и сохранять историю. Кроме того, предполагается, что есть конфликты слияния в dir-to-merge
,
git checkout target-branch
git merge --no-ff --no-commit -X theirs source-branch
# the option "-X theirs", will pick theirs when there is a conflict.
# the options "--no--ff --no-commit" prevent a commit after a merge, and give you an opportunity to fix other directories you want to retain, before you commit this merge.
# the above, would have messed up the other directories that you want to retain.
# so you need to reset them for every directory that you want to retain.
git reset HEAD dir-to-retain
# verify everything and commit.
Когда между текущими коммитами двух ветвей изменилось всего несколько файлов, я вручную объединяю изменения, просматривая разные файлы.
git difftoll <branch-1>..<branch-2>
Что я хочу: интерактивно выбирать фрагменты из ветки (в которой было несколько беспорядочных коммитов) в чистую фиксацию в новой ветке.
git diff
+
git apply
не будет работать, если у вас есть какие-либо двоичные файлы в этом diff.
Мой подход:
# New branch from a clean starting point, e.g. master
git checkout new-clean-branch origin/master
# Get all changes from the messy branch
# (quote the star so your shell doesn't expand it)
git checkout messy-branch -- '*'
# Unstage ("un-add") everything
git restore --staged .
# Interactively add hunks to be staged for commit
git add -p
Я собираюсь сконцентрироваться на подмножестве этой проблемы, которая меня интересовала: у меня две ветки, и я хочу псевдо-слить один файл из одного в другой.
(Я говорю «псевдо-слияние», потому что мне не нужна и не нужна фиксация слияния; я просто хочу объединить вклады обеих версий файла так, как я считаю нужным.)
Мой подход основан на подходе, принятом в /questions/23891223/git-obedinit-tolko-odin-fajl-iz-mastera-v-tekuschuyu-vetku/23891230#23891230. К сожалению, этот вопрос закрыт как дубликат (на мой взгляд, ошибочно: это не дубликат этого вопроса, и неправильно отвечать и закрывать как дубликат, что и сделал там ответчик). Но в этом ответе есть некоторые ошибки, поэтому я модернизировал и очистил подход. Вместо и я использую, и я не беспокоюсь о том, чтобы зафиксировать то, что мне не нужно.
Хорошо, представьте, что у меня есть три файла:
$ ls
a b f
Но я хочу псевдо-объединить только одну из них,
a
, из . Давайте посмотрим на них, чтобы увидеть, как будет выглядеть ситуация. Вот моя версия:
$ cat a
line one
line two
line three
line four
line five
Вот версия другого филиала:
$ git show otherbranch:a
line one
line two edited
line three
line four
line five
line six
Уловка здесь в том, что мы собираемся использовать индекс как блокнот (в конце концов, для чего он нужен). Итак, мы начинаем (ШАГ 1), убедившись, что наша версия скопирована в индекс:
$ git add a
Теперь (ШАГ 2) мы можем использовать для получения версии из (в настоящее время это лучше, чем
checkout
так как это позволяет нам говорить более ясно):
$ git restore --source otherbranch a
На первый взгляд это выглядит плохо. Теперь мы полностью заменили наш a версией из, как вы можете видеть:
Но не волнуйтесь! Предыдущая версия a все еще находится в индексе, как вы можете видеть:
$ git diff a
diff --git a/a b/a
index abf51fa..333614b 100644
--- a/a
+++ b/a
@@ -1,6 +1,7 @@
line one
-line two
+line two edited
line three
line four
line five
+line six
Хорошо, теперь мы готовы к ключевому ходу (ШАГ 3). Делаем интерактивный патч
add
нашего файла из рабочего дерева в index.
Мы могли бы сказать
git add -p a
чтобы запустить интерактивный процесс патча, и в этом случае мы будем кормить ханков по одному. Но в этом случае есть только один кусок, и я все равно хочу его отредактировать, поэтому я говорю:
$ git add --e a
В результате мы открываем патч-файл различий в нашем редакторе! Это выглядит так:
line one
-line two
+line two edited
line three
line four
line five
+line six
Путем тщательного редактирования мы можем теперь решить, какие части мы хотим принять, а какие нет. Примем «строку шесть», но не «строку 2 отредактировали». Итак, мы редактируем, чтобы выглядеть так:
line one
line two
line three
line four
line five
+line six
Мы закрываем редактор, и патч применяется к индексной версии файла. Но мы еще не закончили! В
otherbranch
версия a все еще находится в рабочем дереве:
$ cat a
line one
line two edited
line three
line four
line five
line six
Версия, которая нам нравится, есть в указателе, помните? Чтобы получить его (ШАГ 4), мы просто звоним
git restore
просто и понятно (опять же, по-современному;
restore
лучше чем
reset
и может применяться к одному файлу):
$ git restore a
Теперь наш a правильный, и мы все закончили:
$ cat a
line one
line two
line three
line four
line five
line six
На этом этапе мы могли бы выполнить фиксацию, но это не обязательно; мы выполнили то, что намеревались сделать.
Если вы являетесь пользователем Gitkraken , у вас есть небольшое руководство.
В итоге:
- перейдите в ветку, в которую вы хотите внести изменения. (например, разработать)
- щелкните правой кнопкой мыши ветку с новыми изменениями и выберите опцию « cherrypick commit » (например, feature-ABC).
- Наконец, примите и проверьте наличие конфликтов, если таковые имеются.