Как решить конфликт с git stash без коммитов? - PullRequest
420 голосов
/ 13 октября 2011

Как и спросил в этом вопросе , я также хочу знать, как разрешить конфликтующий git stash pop без добавления всех модификаций в коммит (как это делает «git stash pop» без конфликта).

Мой нынешний подход очень не крутой, потому что я делаю это так:

git stash pop -> CONFLICT
git stash drop
[resolve conflict]
[add conflict files]
git reset HEAD <all files that are in commit-mode>

[Обновление] Способ его воспроизведения:

mkdir foo; cd foo; git init
echo "1" > one
echo "2" > two
git add -A; git commit -m "first"
echo "1.1" > one
echo "2.1" > two
git stash
echo "2.2" > two
git commit -a -m "second"
echo "Only this file would stay in HEAD without the conflict" > third
git add third
git stash pop
git status

2016-06-27: в пример добавлен новый файл с именем «третий», показывающий, что обходные пути, такие как решение от scy, работают только для пустых HEAD, но не устраняют первоначальную проблему, заключающуюся в том, что HEAD не имеет тот же контент, что и для git stash pop без конфликта.

Ответы [ 10 ]

363 голосов
/ 09 декабря 2014

Не следуйте другим ответам

Ну, вы можете следовать за ними :). Но я не думаю, что выполнение коммита, а затем сброс ветки для удаления этого коммита и аналогичные обходные пути, предложенные в других ответах, являются чистым способом решения этой проблемы.

Чистый раствор

Следующее решение кажется мне намного чище, и оно также , предложенное самим Git - попробуйте выполнить git status в хранилище с конфликтом:

Unmerged paths:
  (use "git reset HEAD <file>..." to unstage)
  (use "git add <file>..." to mark resolution)

Итак, давайте сделаем то, что предлагает Git (без каких-либо бесполезных коммитов):

  1. Вручную (или с помощью какого-либо инструмента слияния , см. Ниже) разрешить конфликт (ы).
  2. Используйте git reset, чтобы пометить конфликт (ы) как разрешенные и отменить изменения. Вы можете выполнить его без каких-либо параметров, и Git удалит все из индекса. Вам не нужно выполнять git add раньше.
  3. Наконец, удалите тайник с помощью git stash drop, потому что Git не делает этого при конфликте.

Переведено в командную строку:

$ git stash pop

# ...resolve conflict(s)

$ git reset

$ git stash drop

Объяснение поведения по умолчанию

Существует два способа пометить разрешенные конфликты: git add и git reset. Хотя git reset помечает конфликты как разрешенные и удаляет файлы из индекса, git add также помечает конфликты как разрешенные, но сохраняет файлы в индексе.

Добавление файлов в индекс после разрешения конфликта специально. Таким образом, вы можете отличить изменения от предыдущего тайника и изменения, сделанные после разрешения конфликта. Если вам это не нравится, вы всегда можете использовать git reset, чтобы удалить все из индекса.

Объединение инструментов

Я настоятельно рекомендую использовать для разрешения конфликтов любой из трехсторонних инструментов слияния , например. KDiff3 , Meld и т. Д. Вместо того, чтобы делать это вручную. Обычно он сам решает все или большинство конфликтов автоматически. Это огромный экономия времени!

291 голосов
/ 13 августа 2013

Предположим, у вас есть этот сценарий, в котором вы прячете свои изменения, чтобы вытащить из источника. Возможно, потому что ваши локальные изменения просто debug: true в некоторых файлах настроек. Теперь вы тянете, и кто-то ввел там новую настройку, создающую конфликт.

git status говорит:

# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      src/js/globals.tpl.js
no changes added to commit (use "git add" and/or "git commit -a")

Хорошо. Я решил пойти с тем, что предложил Git: я решил конфликт и совершил:

vim src/js/globals.tpl.js
# type type type …
git commit -a -m WIP   # (short for "work in progress")

Теперь моя рабочая копия находится в том состоянии, в котором я хочу, но я создал коммит, который мне не нужен. Как мне избавиться от этого коммита без изменения моей рабочей копии? Подождите, есть популярная команда для этого!

git reset HEAD^

Моя рабочая копия не была изменена, но фиксация WIP пропала. Это именно то, что я хотел! (Обратите внимание, что я не использую --soft здесь, потому что если в вашем хранилище есть автоматически объединенные файлы, они автоматически размещаются, и, таким образом, вы получите эти файлы снова после reset.)

Но есть еще одна вещь: справочная страница для git stash pop напоминает нам, что "Применение состояния может привести к сбою при конфликтах; в этом случае оно не удаляется из списка хранения. Вам необходимо разрешить конфликтует вручную и впоследствии вызывает git stash drop. " Так что именно это мы и делаем сейчас:

git stash drop

И готово.

84 голосов
/ 28 октября 2011

Вместо добавления изменений, внесенных вами для разрешения конфликта, вы можете использовать git reset HEAD file для разрешения конфликта без постановки изменений.

Однако, возможно, вам придется выполнить эту команду дважды. Один раз, чтобы пометить конфликт как разрешенный, и один раз, чтобы отменить внесение изменений, которые были организованы процедурой разрешения конфликтов.

Возможно, что существует режим сброса, который выполняет обе эти функции одновременно, хотя сейчас его нет.

21 голосов
/ 09 сентября 2014
git checkout stash -- .

работал на меня.

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

6 голосов
/ 28 сентября 2016
git add .
git reset

git add . будет ставить ВСЕ файлы, сообщающие git, что вы разрешили конфликт

git reset будет удалять все поставленные файлы без создания коммита

4 голосов
/ 01 марта 2012

Кажется, это может быть ответ, который вы ищете, я еще не пробовал это лично, но, похоже, это может сработать. С помощью этой команды GIT попытается применить изменения, как они были раньше, не пытаясь добавить их все для фиксации.

git stash apply --index

вот полное объяснение:

http://git -scm.com / книга / а / GIT-Сервис-припрятать

2 голосов
/ 18 сентября 2015

Самый быстрый способ, который я нашел, это разрешить конфликт, затем выполнить git add -u, а затем выполнить git reset HEAD, что даже не требует фиксации.

2 голосов
/ 12 августа 2014

git stash branch будет работать, что создает новую ветку для вас, проверяет коммит, на котором вы были, когда вы спрятали свою работу, повторно применили свою работу там, и затем сбрасывает тайник, если он успешно применяется. отметьте это

1 голос
/ 26 января 2015

Согласно git stash , после исправления конфликта, git add <file> - правильный курс действий.

После прочтения этого комментария яПонятно, что изменения автоматически добавляются в индекс (по замыслу).Вот почему git add <file> завершает процесс разрешения конфликта.

0 голосов
/ 13 декабря 2017

Это не лучший способ сделать это, но он работает:

$ git stash apply
$ >> resolve your conflict <<
$ >> do what you want to do with your code <<
$ git checkout HEAD -- file/path/to/your/file
...