Как Git-cherry-pick изменяет только определенные файлы?
если я хочу объединить в ветку Git изменения, внесенные только в некоторые файлы, измененные в определенном фиксации, которая включает изменения в несколько файлов, как это может быть достигнуто?
предположим, что git commit называется stuff
изменения в файлы A
, B
, C
и D
но я хочу объединить только stuff
изменения в файлах A
и B
. Это звучит как работа для git cherry-pick
но cherry-pick
только знает, как объединить все коммиты, а не подмножество файлы.
10 ответов
Я бы сделал это с cherry-pick -n
(--no-commit
), который позволяет проверить (и изменить) результат перед совершением:
git cherry-pick -n <commit>
# unstage modifications you don't want to keep, and remove the
# modifications from the work tree as well.
# this does work recursively!
git checkout HEAD <path>
# commit; the message will have been stored for you by cherry-pick
git commit
если подавляющее большинство модификаций-это то, чего вы не хотите, вместо того, чтобы проверять отдельные пути (средний шаг), вы можете сбросить все обратно, а затем добавить то, что вы хотите:
# unstage everything
git reset HEAD
# stage the modifications you do want
git add <path>
# make the work tree match the index
# (do this from the top level of the repo)
git checkout .
другие методы не работали для меня, так как фиксация имела много изменений и конфликтов со многими другими файлами. То, что я придумал, было просто
git show SHA -- file1.txt file2.txt | git apply -
на самом деле это не add
файлы или сделать фиксацию для вас, поэтому вам может потребоваться выполнить его с
git add file1.txt file2.txt
git commit -c SHA
или если вы хотите пропустить добавление, вы можете использовать до git apply
git show SHA -- file1.txt file2.txt | git apply --cached -
возможно, преимущество этого метода над Jefromi это это то, что вам не нужно помнить, какое поведение сброс git - правильный :)
# Create a branch to throw away, on which we'll do the cherry-pick:
git checkout -b to-discard
# Do the cherry-pick:
git cherry-pick stuff
# Switch back to the branch you were previously on:
git checkout -
# Update the working tree and the index with the versions of A and B
# from the to-discard branch:
git checkout to-discard -- A B
# Commit those changes:
git commit -m "Cherry-picked changes to A and B from [stuff]"
# Delete the temporary branch:
git branch -D to-discard
Я обычно использую -p
флаг с проверкой git из другой ветви, которую я нахожу проще и более зернистой, чем большинство других методов, с которыми я столкнулся.
в принципе:
git checkout <other_branch_name> <files/to/grab in/list/separated/by/spaces> -p
пример:
git checkout mybranch config/important.yml app/models/important.rb -p
затем вы получаете диалоговое окно с вопросом, какие изменения вы хотите в "blobs" это в значительной степени работает на каждый кусок непрерывного изменения кода, который вы можете затем сигнализировать y
(Да) n
(нет) etc для каждый кусок кода.
на -p
или patch
опция работает для различных команд в git, включая git stash save -p
что позволяет выбрать то, что вы хотите спрятать от вашей текущей работе
Я иногда использую эту технику, когда я сделал много работы и хотел бы отделить ее и совершить в более тематических коммитах, используя git add -p
и выбор того, что я хочу для каждой фиксации:)
Cherry pick-это выбор изменений из определенной "фиксации". Самое простое решение-выбрать все изменения определенных файлов-использовать
git checkout source_branch <paths>...
пример:
$ git branch
* master
twitter_integration
$ git checkout twitter_integration app/models/avatar.rb db/migrate/20090223104419_create_avatars.rb test/unit/models/avatar_test.rb test/functional/models/avatar_test.rb
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: app/models/avatar.rb
# new file: db/migrate/20090223104419_create_avatars.rb
# new file: test/functional/models/avatar_test.rb
# new file: test/unit/models/avatar_test.rb
#
$ git commit -m "'Merge' avatar code from 'twitter_integration' branch"
[master]: created 4d3e37b: "'Merge' avatar code from 'twitter_integration' branch"
4 files changed, 72 insertions(+), 0 deletions(-)
create mode 100644 app/models/avatar.rb
create mode 100644 db/migrate/20090223104419_create_avatars.rb
create mode 100644 test/functional/models/avatar_test.rb
create mode 100644 test/unit/models/avatar_test.rb
источники и полное объяснение http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/
обновление:
С помощью этого метода git не будет объединять файл, он просто переопределит любое другое изменение, сделанное на филиал назначения. Вам нужно будет объединить изменения вручную:
$ git diff Head filename
Я бы просто вишневый выбрать все, а затем сделать это:
git reset --soft HEAD^
затем я бы вернул изменения, которые я не хочу, а затем сделал новую фиксацию.
использовать git merge --squash branch_name
Это получит все изменения из другой ветви и подготовит фиксацию для вас.
Теперь удалите все ненужные изменения и оставьте тот, который вы хотите. И git не будет знать, что произошло слияние.
Я нашел другой способ, который предотвращает любое конфликтное слияние на вишневом сборе, который ИМО легко запомнить и понять. Поскольку вы на самом деле не выбираете фиксацию, а часть ее, вам нужно сначала разделить ее, а затем создать фиксацию, которая будет соответствовать вашим потребностям, и выбрать ее.
сначала создайте ветку из фиксации, которую вы хотите разделить, и проверьте ее:
$ git checkout COMMIT-TO-SPLIT-SHA -b temp
затем верните предыдущую фиксацию:
$ git reset HEAD~1
затем добавить файлы/изменения, которые вы хотите выбрать:
$ git add FILE
и совершил его:
$ git commit -m "pick me"
обратите внимание на хэш фиксации, назовем его PICK-SHA и вернемся к вашей основной ветви, мастер, например, заставляя проверку:
$ git checkout -f master
и берут на себя обязательство:
$ git cherry-pick PICK-SHA
теперь вы можете удалить ветку temp:
$ git branch -d temp -f
объедините ветку в новую (squash) и удалите ненужные файлы:
git checkout master
git checkout -b <branch>
git merge --squash <source-branch-with-many-commits>
git reset HEAD <not-needed-file-1>
git checkout -- <not-needed-file-1>
git reset HEAD <not-needed-file-2>
git checkout -- <not-needed-file-2>
git commit
ситуация:
вы находитесь на своей ветке, скажем master
и у вас есть фиксация на любой другой ветке. Вы должны выбрать только один файл из этой конкретной фиксации.
подход:
Шаг 1: оформить заказ на нужную ветвь.
git checkout master
Шаг 2: убедитесь, что вы скопировали необходимый хэш фиксации.
git checkout commit_hash path\to\file
Шаг 3: теперь у вас есть изменения необходимого файла в нужной ветке. Вам просто нужно добавить и зафиксировать их.
git add path\to\file
git commit -m "Your commit message"