Как 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 reset это правильно:)
# 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 для каждый кусок кода.The
-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 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
объединить ветку в новую (сквош) и удалить ненужные файлы:
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"