Разница между git reset и git cherry-pick

Я прочитал с https://github.com/blog/2019-how-to-undo-almost-anything-with-git это:

Если вы хотите восстановить историю проекта такой, какой она была на тот момент, используйте git reset --hard. Если вы хотите воспроизвести только один из этих коммитов в свой репозиторий, используйте git cherry-pick .

Я новичок и еще не занимался ветвлением. Мне кажется, что использование cherry-pick здесь идентично git reset. Я хочу знать, что на самом деле git cherry-pick отличается от git reset , учитывая, что я работаю только в одной ветке.


person Chirag    schedule 12.01.2017    source источник


Ответы (2)


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

git checkout foo
#you are in branch foo. you make some EDITS on this branch.
git commit -am "my changes to foo branch"
git push 
#The commit, say sha1, is pushed to foo branch.

### several other commits are pushed randomly by different users to this branch ###

Допустим, другой пользователь хочет перенести эту фиксацию, sha1, из ветки foo в ветку bar того же репозитория. Обратите внимание, что в этом случае ветвь foo может опережать несколько коммитов по состоянию фиксации sha1.

foo : ORIG_HEAD -- sha1 -- sha2 -- sha3 -- .... shaN
                    ^~~~user want to cherry-pick 
                        only this commit

Чтобы выбрать фиксацию sha1 в ветке bar:

git checkout bar
git cherry-pick sha1 
# The commit `sha1` is merged to your branch `bar` and is ahead by 1 commit

Git reset в основном используется для отмены локальных коммитов или неудачных git pull/merge. Он также используется для устранения беспорядка в грязном рабочем дереве.

Например:

$ git pull    
  Automatic merge failed; fix conflicts and then commit the result.
$ git reset --hard   # clears the mess from the index file and the working tree.

Таким образом, и выбор вишни, и git-reset влияют на положение HEAD, но они сильно различаются с точки зрения вариантов использования.

person Saurav Sahu    schedule 22.01.2017

git reset --hard означает git reset --hard HEAD, где HEAD — это ссылка (ссылка) на текущую проверенную фиксацию или последнюю фиксацию в вашей текущей ветке, т. е. не меняйте ветку, но избавляйтесь от всех локальных изменений, чтобы удалить все поэтапные и неустановленные изменения. Команда git reset предоставляет множество опций, которые очень хорошо объясняются здесь:

Можете ли вы объяснить, что делает git reset простым английским языком?< /а>

Принимая во внимание, что выбор вишни означает выбор фиксации из одной ветки и применение ее к другой. Это можно сделать, если вы, например. допустил ошибку и внес изменения в неправильную ветку, но не хочет объединять всю ветку. Вы можете просто, например. отменить фиксацию и выбрать ее в другой ветке.

Если в случае, если вы нажимаете не на ту ветку или у вас есть проблемы с вашей веткой, которая показывает много коммитов от других пользователей (когда работают несколько пользователей) из-за старой истории git в вашей системе, вы можете удалить текущую ветку, сохранив вашу фиксацию безопасные хэши, а затем вишневый выбор коммитов в новую ветку, которая будет обновлена ​​​​из мастера. (Этот случай иногда случается, и cherry-pick является вариантом, когда rebase или merge не решает проблему)

Цитата взята из этого ответа:

Источник: https://stackoverflow.com/a/30218784/4207394

Использование git cherry-pick Команда git cherry-pick commit применяет изменения, внесенные именованным коммитом, в текущую ветку. Он представит новую, отдельную фиксацию. Строго говоря, использование git cherry-pick не изменяет существующую историю в репозитории; вместо этого он добавляет к истории. Как и в случае с другими операциями Git, которые вносят изменения в процессе применения различий, вам может потребоваться разрешить конфликты, чтобы полностью применить изменения из данного коммита. Команда git cherry-pick обычно используется для внесения определенных коммитов из одной ветки в репозиторий в другую ветку. Обычно используется для пересылки или обратного переноса коммитов из ветки обслуживания в ветку разработки.

Поэтому всякий раз, когда вы хотите сбросить коммит или ваши изменения, вы можете использовать git reset и событие, если вы хотите сбросить коммит и сохранить изменения в безопасности этого коммита, вы можете использовать git reset с опцией --soft. И если вы хотите скопировать коммит из какой-то другой ветки в какую-то другую, вы можете использовать git cherry-pick. git reset имеет множество доступных опций, например:

Чтобы сбросить на текущий HEAD:

git reset --hard HEAD

Чтобы сбросить один коммит и удалить изменения:

git reset --hard HEAD~1

это 1 может быть n для удаления любого количества коммитов. А также для сохранения изменений коммитов можно использовать --soft вместо --hard.

Для cherry-pick синтаксис такой:

git cherry-pick <commit-hash>
person Deepesh    schedule 12.01.2017
comment
Поэтому я удаляю текущую ветку, сохраняя хэши своих коммитов в безопасности, а затем выбираю коммиты для моей новой ветки. Было бы полезно здесь перебазировать master в вашу функциональную ветку? (Я имею в виду git rebase master, когда вы находитесь в ветке функций). - person Oleg Arkhipov; 12.01.2017
comment
@Construct Да, это может быть полезно, но становится сложно, когда работают 6-7 разработчиков, и вы полностью перестраиваете сайт со многими новыми функциями, которые были добавлены в этот раз, когда rebase вызовет много конфликтов. - person Deepesh; 12.01.2017
comment
Разве не возникнут все эти конфликты, если вы тоже будете выбирать вишни? Вам все равно придется как-то решать конфликты между вашим кодом и изменениями в diverged master, если они есть. - person Oleg Arkhipov; 12.01.2017
comment
@Construct Я обновил свое заявление, потому что понял вашу озабоченность и не смог четко объяснить эту проблему. Эта проблема возникает, когда у вас старая история git, и вы давно ее не обновляли. Затем иногда в вашей функциональной ветке он начинает показывать коммиты других пользователей, но никаких дополнительных изменений в файлах. В этом случае вы можете это сделать. - person Deepesh; 12.01.2017
comment
@Construct: да, будут. На самом деле git rebase — это просто автоматизированная серия операций выбора вишни, за которыми в конце следует перемещение перебазированной ветки, чтобы она указывала на последний такой выбранный коммит. - person torek; 12.01.2017
comment
Спасибо вам обоим за объяснение. @Deep, я просто никогда не встречал такой ситуации. - person Oleg Arkhipov; 12.01.2017
comment
@torek Итак, будет ли разница в перебазировании и выборе вишни, верно? Вишневый выбор, который вы сделаете, будет связан с вашими коммитами, а rebase будет воспроизводить ваш коммит на коммитах основной ветки? - person Deepesh; 12.01.2017
comment
@Deep: git cherry-pick означает копирование одного коммита. Вы выбираете фиксацию, она добавляется как новая фиксация, где бы вы сейчас ни находились. (Вы можете скопировать более одного, но по умолчанию используется только один.) С другой стороны, git rebase означает: копировать столько коммитов, сколько необходимо, из текущей ветки, где я сейчас, туда куда я скажу вам переместиться; а затем переместите мою текущую ветку в последний скопированный коммит. Последний шаг — перемещение ветки — фактически удаляет исходный (теперь уже скопированный) коммит из этой ветки. (Что хорошо, потому что они скопированы.) Так что они очень разные. - person torek; 12.01.2017
comment
@Deep: копировать столько коммитов, сколько необходимо, буквально использует вишневый выбор, если вы используете git rebase -i (он может использовать альтернативный механизм для неинтерактивной перебазировки). Вот почему вы получаете редактор с кучей команд выбора: это те коммиты, которые нужно выбирать. Однако шаг отбрасывания является новым, и основная цель всего копирования заключается в том, чтобы новые копии появлялись в другой точке графа коммитов. Вы можете посмотреть, например, stackoverflow.com/q/39154794/1256452 здесь. - person torek; 12.01.2017
comment
@torek Спасибо за объяснение, я знаю разницу между cherry-pick и rebase, но, как вы упомянули, rebase использует cherry-pick внутри, поэтому просто уточнил, что оба будут разными. Предположим, что в ветке, которую вы хотите перебазировать, есть только одна фиксация, поэтому вы можете cherry-pick или rebase, поэтому в этом случае оба будут разными (разница будет в редком случае, когда git automerge объединяет файлы). Надеюсь, мне понятно, что я пытаюсь сказать. - person Deepesh; 12.01.2017
comment
Что ж, это заходит глубоко в сорняки, потому что, как я уже упоминал, rebase может на самом деле запускать git cherry-pick, а может запускать git format-patch ... | git am .... Оба попытаются сделать одно и то же в случаях, требующих слияния, но в случае переименования больше подходит форма выбора вишни. Вот почему современный git rebase имеет аргумент флага -m, чтобы заставить его использовать git cherry-pick, а не git format-patch. Но в целом да: если есть только один коммит для копирования, вы можете сделать это тремя командами Git git checkout; git cherry-pick; git branch -f вместо 1 git rebase. - person torek; 12.01.2017
comment
@torek Хорошо, спасибо за объяснение. Честно говоря, я не знаю, что git rebase делает внутри, но я прочитаю об этом и ссылку на ваш ответ, который вы предоставили выше. Есть некоторые проблемы, которые не могут быть точно объяснены или воспроизведены, поскольку они полностью зависят от того, как вы используете git и git, которые настолько обширны, что трудно знать каждую вещь. Но такие комментарии и такие пользователи, как вы, помогают мне учиться этим вещам. :-) - person Deepesh; 12.01.2017