Практическое использование git reset --soft?
Я работаю с git чуть больше месяца. Действительно, я использовал reset впервые только вчера, но мягкий reset до сих пор не имеет большого смысла для меня.
Я понимаю, что я могу использовать soft reset для редактирования фиксации без изменения индекса или рабочего каталога, как и с git commit --amend
.
Являются ли эти две команды одинаковыми (reset --soft
vs commit --amend
)? Любая причина использовать тот или иной в практическом смысле? И что еще более важно, существуют ли какие-либо другие применения для reset --soft
помимо внесения изменений в коммит?
Ответы
Ответ 1
git reset
- все о перемещении HEAD
.
Вопрос: как насчет рабочего дерева и индекса?
При использовании с --soft
, перемещается HEAD
и только HEAD
.
Это отличается от commit --amend
следующим образом:
- он не создает новую фиксацию.
- он может фактически переместить HEAD в любое commit (поскольку
commit --amend
означает только перемещение HEAD, позволяя повторить текущую фиксацию)
Просто нашел этот пример объединения:
- классическое объединение
- слияние поддерева
все в одно (осьминог, поскольку сливается более двух ветвей) commit merge.
Tomas "areHamster" Carnecky объясняет в своем "Subtree Octopus merge" статья:
- Стратегия слияния поддерева может использоваться, если вы хотите объединить один проект в подкаталог другого проекта и впоследствии сохранить подпроект в актуальном состоянии. Это альтернатива подмодулям 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 [email protected]{2}
Теперь мы можем возобновить решение Tomas:
# 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
- это ответ.
Ответ 2
Use Case - объединить ряд локальных коммитов
"Эти три фиксации могут быть только одним".
Итак, отмените последние 3 (или что-то другое), зафиксировав (не затрагивая индекс и рабочий каталог). Затем выполните все изменения как.
например.
> git add -A; git commit -m "Start here."
> git add -A; git commit -m "One"
> git add -A; git commit -m "Two"
> git add -A' git commit -m "Three"
> git log --oneline --graph -4 --decorate
> * da883dc (HEAD, master) Three
> * 92d3eb7 Two
> * c6e82d3 One
> * e1e8042 Start here.
> git reset --soft HEAD~3
> git log --oneline --graph -1 --decorate
> * e1e8042 Start here.
Теперь все ваши изменения сохранены и готовы быть зафиксированными как один.
Краткие ответы на ваши вопросы
Являются ли эти две команды одинаковыми (reset --soft
vs commit --amend
)?
Любая причина использовать тот или иной на практике?
-
commit --amend
добавить /rm файлы с самого последнего фиксации или изменить его сообщение.
-
reset --soft <commit>
, чтобы объединить несколько последовательных коммитов в новый.
И что еще более важно, есть ли какие-либо другие применения для reset --soft
, кроме внесения изменений в коммит?
Ответ 3
Я использую его для изменения больше, чем только последнее коммит.
Скажем, я совершил ошибку в совершении A, а затем сделал фиксацию B. Теперь я могу только изменить B.
Поэтому я выполняю git reset --soft HEAD^^
, я исправляю и повторно фиксирую A, а затем повторно фиксирую B.
Конечно, это не очень удобно для больших коммитов... но вы не должны делать большие коммиты в любом случае; -)
Ответ 4
Другое потенциальное использование - альтернатива краже (что не нравится некоторым людям, см., Например, https://codingkilledthecat.wordpress.com/2012/04/27/git-stash-pop-considered-harmful/).
Например, если я работаю над веткой и мне нужно срочно что-то исправить на master, я могу просто сделать:
git commit -am "In progress."
затем осмотрите мастер и сделайте исправление. Когда я закончу, я возвращаюсь в свою ветку и делаю
git reset --soft HEAD~1
продолжать работать там, где я остановился.
Ответ 5
Вы можете использовать git reset --soft
, чтобы изменить версию, которую вы хотите иметь в качестве родителя, для изменений, которые у вас есть в вашем индексе и рабочем дереве. Случаи, когда это полезно, редки. Иногда вы можете решить, что изменения, которые у вас есть в рабочем дереве, должны принадлежать другому ветки. Или вы можете использовать это как простой способ свернуть несколько коммитов в один (аналогично squash/fold).
См. этот ответ VonC для практического примера:
Сквош первых двух коммитов в Git?
Ответ 6
Одним из возможных вариантов использования будет то, когда вы хотите продолжить свою работу на другой машине. Он будет работать следующим образом:
-
Оформить новую ветку с тиковым именем,
git checkout -b <branchname>_stash
-
Нажмите на свою ветку,
git push -u origin <branchname>_stash
-
Перейдите на другую машину.
-
Потяните вниз свой трюк и существующие ветки,
git checkout <branchname>_stash; git checkout <branchname>
-
Теперь вы должны быть в своей существующей ветке. Слияние изменений с ветки штампа,
git merge <branchname>_stash
-
Мягкая reset ваша существующая ветвь до 1 до слияния,
git reset --soft HEAD^
-
Удалите свою ветку штока,
git branch -d <branchname>_stash
-
Также удалите свою ветку стаи с начала,
git push origin :<branchname>_stash
-
Продолжайте работать с вашими изменениями, как если бы вы их обыграли.
Думаю, в будущем GitHub и co. должен предлагать эту функциональность "удаленного тайника" за меньшее количество шагов.
Ответ 7
Поводом использовать 'git reset --soft <sha1>
' является перенос HEAD
в голое репо.
Если вы попытаетесь использовать параметр --mixed
или --hard
, вы получите сообщение об ошибке, так как вы пытаетесь изменить и работать с деревом и/или индексом, который не существует.
Примечание. Вам нужно будет сделать это прямо из голого репо.
Примечание. Еще раз: вам нужно убедиться, что ветка, которую вы хотите использовать reset в голом репо, является активной ветвью. Если нет, следуйте VonC answer о том, как обновить активную ветвь в режиме открытого репо, когда у вас есть прямой доступ к репо.
Ответ 8
Одним из практических применений является то, что если вы уже зафиксировали свое локальное репо (т.е. git commit -m), то вы можете отменить этот последний коммит, выполнив git reset --soft HEAD ~ 1
Также, насколько вам известно, если вы уже подготовили свои изменения (например, с помощью git add.), То вы можете отменить размещение, выполнив git reset - -m ixed HEAD, или я обычно также только что использовал git reset
наконец, git reset --hard уничтожает все, включая ваши локальные изменения. Глава ~ after сообщает вам, сколько человек совершает переход сверху.
Ответ 9
SourceTree - это графический интерфейс git, который имеет довольно удобный интерфейс для размещения только тех бит, которые вы хотите. Он не имеет ничего удаленного, чтобы изменить правильную версию.
Так что git reset --soft HEAD~1
гораздо более полезен, чем commit --amend
в этом сценарии. Я могу отменить фиксацию, вернуть все изменения в промежуточную область и возобновить настройку поэтапных битов с помощью SourceTree.
Действительно, мне кажется, что commit --amend
- более избыточная команда этих двух, но git - git и не уклоняется от подобных команд, которые делают несколько разные вещи.
Ответ 10
Хотя мне действительно нравятся ответы в этой теме, я использую git reset --soft
для немного другого, но, тем не менее, очень практичного сценария.
Я использую среду разработки для разработки, которая имеет хороший инструмент сравнения для отображения изменений (поэтапных и неустановленных) после моей последней фиксации. Теперь большинство моих задач связаны с несколькими коммитами. Например, допустим, я сделал 5 коммитов для выполнения определенной задачи. Я использую инструмент сравнения в IDE во время каждого добавочного коммита от 1 до 5, чтобы посмотреть мои изменения с последнего коммита. Я считаю, что это очень полезный способ проверить мои изменения перед их фиксацией.
Но в конце моей задачи, когда я хочу увидеть все свои изменения вместе (до 1-го коммита), сделать самоконтроль кода перед выполнением запроса на извлечение, я увижу только изменения из моего предыдущего коммита (после коммита) 4) и не меняется от всех коммитов моей текущей задачи.
Поэтому я использую git reset --soft HEAD~4
чтобы вернуться к 4 коммитам. Это позволяет мне видеть все изменения вместе. Когда я буду уверен в своих изменениях, я смогу выполнить git reset [email protected]{1}
и с уверенностью передать ее на удаленное устройство.
Ответ 11
Другой вариант использования - это когда вы хотите заменить другую ветку своей в запросе на извлечение, например, предположим, что у вас есть программное обеспечение с функциями A, B, C в разработке.
Вы разрабатываете со следующей версией и вы:
-
Удалена функция B
-
Добавлена функция D
В процессе, разработайте только что добавленные исправления для функции B.
Вы можете объединить разработку в следующую, но иногда это может быть грязно, но вы также можете использовать git reset --soft origin/develop
и создать коммит с вашими изменениями, и ветка будет объединяться без конфликтов и сохранять ваши изменения.
Оказывается, git reset --soft
- удобная команда. Лично я часто использую его для сжатия коммитов, которые не имеют "завершенной работы", как "WIP", поэтому, когда я открываю запрос на извлечение, все мои коммиты понятны.