Практическое использование 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", поэтому, когда я открываю запрос на извлечение, все мои коммиты понятны.