Как выборочно объединить или выбрать изменения из другой ветки в Git?

Я использую git для нового проекта, который имеет две параллельные - но в настоящее время экспериментальные - ветви разработки:

  • master: импорт существующей кодовой базы плюс несколько модов, в которых я обычно уверен
  • exp1: экспериментальный филиал № 1
  • exp2: экспериментальный филиал № 2

exp1 а также exp2 представляют два очень разных архитектурных подхода. Пока я не продвинусь дальше, у меня нет никакого способа узнать, какой из них (если любой) будет работать. Поскольку я делаю успехи в одной ветви, у меня иногда есть изменения, которые были бы полезны в другой ветви и хотели бы объединить только те.

Каков наилучший способ объединения выборочных изменений из одной ветви разработки в другую, оставляя после себя все остальное?

Подходы, которые я рассмотрел:

  1. git merge --no-commit с последующей ручной постановкой большого количества правок, которые я не хочу делать общими между ветвями.

  2. Ручное копирование общих файлов во временный каталог с последующим git checkout перейти к другой ветке и затем вручную скопировать ее из временного каталога в рабочее дерево.

  3. Вариация на выше. Отказаться от 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

Если вы обнаружите, что слияние нежелательно, вы можете

  1. редактировать файл напрямую
  2. спасти
  3. 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.

  1. Создайте (если не создали) локальную ветвь с изменениями, которые вы хотите внести.

    $ git branch mybranch <base branch>

  2. Переключитесь на это.

    $ git checkout mybranch

  3. Внесите необходимые изменения из учетной записи другого человека. Если вы еще этого не сделали, вам нужно добавить их в качестве удаленного.

    $ git remote add repos-w-changes <git url>

  4. Сноси все с их ветки.

    $ git pull repos-w-changes branch-i-want

  5. Просмотрите журналы фиксации, чтобы увидеть, какие изменения вы хотите:

    $ git log

  6. Вернитесь к ветке, в которую хотите внести изменения.

    $ git checkout originalbranch

  7. Черри выбирает ваши коммиты, один за другим, с помощью хешей.

    $ 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 , у вас есть небольшое руководство.

В итоге:

  1. перейдите в ветку, в которую вы хотите внести изменения. (например, разработать)
  2. щелкните правой кнопкой мыши ветку с новыми изменениями и выберите опцию « cherrypick commit » (например, feature-ABC).
  3. Наконец, примите и проверьте наличие конфликтов, если таковые имеются.
Другие вопросы по тегам