git reset
это все о переезде HEAD
, и вообще ветка исх .
Вопрос: как насчет рабочего дерева и индекса?
При применении с --soft
, движется HEAD
, чаще обновляя ветви реф, и толькоHEAD
.
Это отличается от commit --amend
как:
- это не создает новый коммит.
- на самом деле он может переместить HEAD в любой коммит (как
commit --amend
только в том случае, если не переместить HEAD, при этом позволяя повторить текущий коммит)
Просто нашел этот пример объединения:
- классическое слияние
- объединение поддеревьев
все в одну (осьминог, так как объединено более двух веток) совершить слияние.
Томас "wereHamster" Карнекки объясняет в своей статье "Слияние поддеревьев осьминога" :
- Стратегия слияния поддеревьев может использоваться, если вы хотите объединить один проект с подкаталогом другого проекта и впоследствии поддерживать подпроект в актуальном состоянии. Это альтернатива подмодулям git.
- Стратегия слияния осьминога может быть использована для слияния трех или более веток. Обычная стратегия может объединять только две ветви, и если вы попытаетесь объединить больше, git автоматически вернется к стратегии осьминога.
Проблема в том, что вы можете выбрать только одну стратегию. Но я хотел объединить их, чтобы получить чистую историю, в которой весь репозиторий атомарно обновляется до новой версии.
У меня есть суперпроект, давайте назовем его projectA
, и подпроект projectB
, который я объединил в подкаталог projectA
.
(это часть слияния поддерева)
Я также поддерживаю несколько местных коммитов.
ProjectA
регулярно обновляется, обновляется projectB
каждые пару дней или недель и обычно зависит от конкретной версии projectA
.
Когда я решаю обновить оба проекта, я не просто извлекаю projectA
и projectB
создаю две коммиты для того, что должно быть атомным обновлением всего проекта .
Вместо этого я создаю один коммит, который объединяет projectA
, projectB
и мои локальные коммиты .
Сложность в том, что это слияние осьминога (три головы), но его projectB
необходимо объединить со стратегией поддеревьев . Вот что я делаю:
# Merge projectA with the default strategy:
git merge projectA/master
# Merge projectB with the subtree strategy:
git merge -s subtree projectB/master
Здесь автор использовал reset --hard
, а затем, read-tree
чтобы восстановить то, что первые два слияния сделали с рабочим деревом и индексом, но вот где reset --soft
можно помочь:
Как мне повторить те два слияния , которые сработали, то есть мое рабочее дерево и индекс хорошо, но без записи этих двух коммитов?
# Move the HEAD, and just the HEAD, two commits back!
git reset --soft HEAD@{2}
Теперь мы можем возобновить решение Томаса:
# Pretend that we just did an octopus merge with three heads:
echo $(git rev-parse projectA/master) > .git/MERGE_HEAD
echo $(git rev-parse projectB/master) >> .git/MERGE_HEAD
# And finally do the commit:
git commit
Итак, каждый раз:
- вы довольны тем, что вы в итоге (с точки зрения рабочего дерева и индекса)
- Вы не удовлетворены всеми коммитами, которые потребовали вас, чтобы попасть туда:
git reset --soft
это ответ.
git reset --soft
: stackoverflow.com/questions/6869705/…Вариант использования - объединение ряда локальных коммитов
«Упс. Эти три коммита могут быть только одним».
Таким образом, отмените последние 3 (или что-то еще) коммитов (не затрагивая ни индекс, ни рабочий каталог). Затем зафиксируйте все изменения как одно.
Например
Теперь все ваши изменения сохранены и готовы к принятию как единое целое.
Короткие ответы на ваши вопросы
Эти две команды действительно одинаковы (
reset --soft
противcommit --amend
)?Есть ли причина использовать тот или иной на практике?
commit --amend
чтобы добавить файлы / rm из самого последнего коммита или изменить его сообщение.reset --soft <commit>
объединить несколько последовательных коммитов в новый.И что еще более важно, есть ли другие варианты использования
reset --soft
помимо внесения изменений в коммит?источник
reset --soft
кроме внесения поправок в коммит - Нет»git reset
) хороши, когда вы (а) хотите переписать историю, (б) не заботитесь о старых коммитах (чтобы вы могли избежать суетливости интерактивного ребазирования) и (в) нужно изменить более одной фиксации (в противном случаеcommit --amend
это проще).Я использую его для исправления не только последнего коммита.
Допустим, я сделал ошибку при фиксации A, а затем совершил фиксацию B. Теперь я могу исправить только B. Итак
git reset --soft HEAD^^
, я исправляю и повторно фиксирую A, а затем повторно фиксирую B.Конечно, для больших коммитов это не очень удобно… но все равно не стоит делать большие коммиты ;-)
источник
git commit --fixup HEAD^^
git rebase --autosquash HEAD~X
тоже хорошо работает.git rebase --interactive HEAD^^
где вы выбираете редактировать как коммиты A, так и B. Таким образом сохраняются сообщения коммитов A и B, при необходимости вы все равно можете изменить их.git reset A
, сделать и добавить изменения,git commit --amend
,git cherry-pick <B-commit-hash>
.Другое возможное использование - это альтернатива хранению (что некоторым не нравится, см., Например, https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/ ).
Например, если я работаю над веткой и мне нужно срочно что-то исправить на мастере, я могу просто сделать:
затем мастер оформления заказа и исправьте ошибку. Когда я закончу, я вернусь в свою ветку и сделаю
продолжить работу с того места, где я остановился.
источник
--soft
на самом деле здесь не нужно, если вы действительно не заботитесь о немедленной постановке изменений. Я сейчас просто используюgit reset HEAD~
при этом. Если у меня есть какие-то изменения, когда мне нужно переключить ветки, и я хочу сохранить это таким образом, то я делаюgit commit -m "staged changes"
, затемgit commit -am "unstaged changes"
, а затем , затем , затемgit reset HEAD~
,git reset --soft HEAD~
чтобы полностью восстановить рабочее состояние. Хотя, честно говоря, сейчас я делаю обе эти вещи намного меньше, чем знаюgit-worktree
:)Вы можете использовать,
git reset --soft
чтобы изменить версию, которую вы хотите использовать в качестве родительской для изменений, которые вы имеете в своем индексе и рабочем дереве. Случаи, когда это полезно, редки. Иногда вы можете решить, что изменения, внесенные в ваше рабочее дерево, должны принадлежать другой ветви. Или вы можете использовать это как простой способ свернуть несколько коммитов в один (аналогично сжатию / сворачиванию).Посмотрите этот ответ VonC для практического примера: Squash первых двух коммитов в Git?
источник
git reset --soft anotherBranch
а затем фиксирую там? Но вы на самом деле не меняете ветку ckeckout, так что вы сделаете фиксацию в Branch или в другомBranch ?Один из возможных вариантов использования - это когда вы хотите продолжить работу на другом компьютере. Это будет работать так:
Оформить заказ на новую ветку с именем, похожим на тайник,
Поднимите ветку тайника вверх,
Переключитесь на другую машину.
Вытащите как свой тайник, так и существующие ветки,
Теперь вы должны быть в существующей ветке. Слить изменения из ветки тайника,
Мягкий сброс существующей ветки до 1 перед слиянием,
Удалите ветку тайника,
Также удалите ветку тайника из источника,
Продолжайте работать со своими изменениями, как если бы вы их обычно прятали.
Я думаю, что в будущем GitHub и компания. должен предлагать эту функцию «удаленного тайника» за меньшее количество шагов.
источник
Одно из практических применений - если вы уже сделали привязку к своему локальному репо (например, git commit -m), вы можете отменить эту последнюю фиксацию, выполнив git reset --soft HEAD ~ 1
Также для вашего знания, если вы уже подготовили свои изменения (например, с помощью git add.), Вы можете отменить постановку, выполнив git reset --mixed HEAD, или я обычно просто использовал
git reset
наконец, git reset --hard стирает все, включая ваши локальные изменения. Знак ~ after head сообщает вам, сколько коммитов нужно перейти сверху.
источник
git reset --soft HEAD ~1
дает мне,fatal: Cannot do soft reset with paths.
я думаю, нам нужно удалить пробел после HEAD, чтобы это былоgit reset --soft HEAD~1
Отличная причина использовать '
git reset --soft <sha1>
' - переместитьHEAD
это использовать чистый репо.Если вы попытаетесь использовать
--mixed
или--hard
, вы получите сообщение об ошибке, поскольку вы пытаетесь изменить и работать с деревом и / или индексом, которые не существуют.Примечание: вам нужно будет сделать это прямо из чистого репо.
Еще раз примечание: вам нужно будет убедиться, что ветка, которую вы хотите сбросить в голом репо, является активной веткой. Если нет, следуйте ответу VonC о том, как обновить активную ветку в голом репо, когда у вас есть прямой доступ к репо.
источник
SourceTree - это графический интерфейс git, который имеет довольно удобный интерфейс для размещения именно тех битов, которые вам нужны. В нем нет ничего отдаленно похожего на внесение поправок в надлежащую версию.
Так
git reset --soft HEAD~1
гораздо полезнее, чемcommit --amend
в этом сценарии. Я могу отменить фиксацию, вернуть все изменения в промежуточную область и возобновить настройку поэтапных битов с помощью SourceTree.На самом деле, мне кажется, что
commit --amend
это более избыточная команда из двух, но git - это git, и он не уклоняется от похожих команд, которые делают немного разные вещи.источник
Хотя мне очень нравятся ответы в этой ветке, я,
git reset --soft
тем не менее , использую несколько другой, но очень практичный сценарий.Я использую IDE для разработки, в которой есть хороший инструмент сравнения для отображения изменений (поэтапных и неустановленных) после моей последней фиксации. Теперь большинство моих задач включают несколько коммитов. Например, предположим, что я делаю 5 коммитов для выполнения определенной задачи. Я использую инструмент diff в среде IDE во время каждой инкрементальной фиксации с 1 по 5, чтобы посмотреть мои изменения из последней фиксации. Я считаю, что это очень полезный способ просмотреть свои изменения перед фиксацией.
Но в конце моей задачи, когда я хочу увидеть все свои изменения вместе (до 1-го коммита), чтобы выполнить самопроверку кода перед выполнением запроса на перенос, я бы увидел только изменения из моей предыдущей фиксации (после фиксации 4), а не изменения из всех коммитов моей текущей задачи.
Поэтому я
git reset --soft HEAD~4
возвращаюсь на 4 коммита назад. Это позволяет мне видеть все изменения вместе. Когда я уверен в своих изменениях, я могу уверенно вносить измененияgit reset HEAD@{1}
и отправлять их на удаленный доступ.источник
git add --patch
иgit commit
повторно создать коммит серию вы бы построить , если бы вы знали , что вы делали все вместе. Ваши первые коммиты похожи на заметки на вашем столе или первый черновик заметки, они нужны для организации вашего мышления, а не для публикации.git reset @{1}
чтобы восстанавливать свои первые черновики серии, вы можете вместо этого создать серию для публикации изgit add -p
иgit commit
.Другой вариант использования - когда вы хотите заменить другую ветку своей в запросе на перенос, например, допустим, что у вас есть программное обеспечение с функциями A, B, C в разработке.
Вы разрабатываете следующую версию и:
Удалена функция B
Добавлена функция D
В процессе разработки только что добавленные исправления для функции B.
Вы можете объединить разработку в следующую, но иногда это может быть беспорядочно, но вы также можете использовать
git reset --soft origin/develop
и создать фиксацию с вашими изменениями, и ветка может быть объединена без конфликтов и сохранить ваши изменения.Оказывается,
git reset --soft
это удобная команда. Лично я часто использую его для сквоша коммитов, которые не имеют «завершенной работы», такой как «WIP», поэтому, когда я открываю пул реквест, все мои коммиты понятны.источник