Git Stash промах: Git Stash поп и закончился конфликтами слияния

200

Я сделал git stash popи закончился конфликтами слияния. Я удалил файлы из файловой системы и сделал, git checkoutкак показано ниже, но он думает, что файлы все еще не объединены. Затем я попытался заменить файлы и сделать то git checkoutже самое. Я событие пытался заставить его с -fфлагом. Любая помощь будет оценена!

chirag-patels-macbook-pro:haloror patelc75$ git status
app/views/layouts/_choose_patient.html.erb: needs merge
app/views/layouts/_links.html.erb: needs merge
# On branch prod-temp
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   db/schema.rb
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       unmerged:   app/views/layouts/_choose_patient.html.erb
#       unmerged:   app/views/layouts/_links.html.erb

chirag-patels-macbook-pro:haloror patelc75$ git checkout app/views/layouts/_choose_patient.html.erb
error: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
chirag-patels-macbook-pro:haloror patelc75$ git checkout -f app/views/layouts/_choose_patient.html.erb
warning: path 'app/views/layouts/_choose_patient.html.erb' is unmerged
Чираг Патель
источник
Примечание: восстановление состояния до этого git stash apply/popдолжно быть проще с Git 2.5 (2 квартал 2015 года), так как рабочее дерево теперь должно быть чистым: см. Мой ответ ниже
VonC

Ответы:

219

Смотрите man git merge ( КАК РАЗРЕШИТЬ КОНФЛИКТЫ ):

Увидев конфликт, вы можете сделать две вещи:

  • Решите не сливаться. Единственная очистка, которая вам нужна, - это сброс файла индекса до фиксации HEAD для отмены 2. и очистка изменений рабочего дерева, сделанных на 2. и 3 .; Для этого можно использовать git-reset --hard.

  • Разрешить конфликты. Git отметит конфликты в рабочем дереве. Отредактируйте файлы в форму и добавьте их в указатель. Используйте git commit, чтобы запечатать сделку.

И в разделе ИСТИННОЕ СЛОВО (чтобы увидеть, что относится к пунктам 2. и 3.):

Когда не очевидно, как согласовать изменения, происходит следующее:

  1. Указатель HEAD остается прежним.

  2. Ссылка MERGE_HEAD установлена ​​так, чтобы указывать на другую ветку ветки.

  3. Точно слитые пути обновляются как в файле индекса, так и в вашем рабочем дереве.

  4. ...

Итак: используйте, git reset --hardесли вы хотите удалить изменения тайника из вашего рабочего дерева, или git resetесли вы хотите просто очистить индекс и оставить конфликты в вашем рабочем дереве для объединения вручную.

Под man git stash ( OPTIONS, pop ) вы можете прочитать дополнительно:

Применение государства может потерпеть неудачу с конфликтами; в этом случае он не удаляется из списка. Вам нужно разрешить конфликты вручную и вручную вызвать git stash drop.

tanascius
источник
9
На самом деле, даже после того, как вы уронили тайник, все еще возможно (хотя и сложнее) восстановить его снова, потому что набор изменений все еще существует в хранилище. stackoverflow.com/search?q=git+recover+dropped+stash
Фил
3
@nalply: это хорошо или плохо?
Пожалуйста,
1
Я думаю, что пересмотр исходного кода является сложной проблемной областью. Это легко запутаться. Я все еще думаю, что ваш ответ хорош, потому что он подтвердил мой подход.
Вскоре
1
Это не только помогло мне понять, что тайник не был удален, как я предполагал, но это объясняет, почему мой тайник продолжал расти, даже когда я был уверен, что не забыл извлечь из него вещи.
Thor84no
11
«Применение состояния может завершиться с конфликтом; в этом случае оно не удаляется из списка хранения».Это самая важная часть поста, на мой взгляд. Попробуйте отредактировать свой ответ, чтобы поставить его в начале вместе со словами « НЕ ПАНИКА» большими, дружескими буквами. (+1 уже хотя.) Спасибо.
Патрик М
42

У меня было нечто подобное со мной. Я пока не хотел ставить файлы, поэтому добавил их, git addа потом просто сделал git reset. Это в основном только что добавило и затем unstaged мои изменения, но очистило необработанные пути.

Аарон
источник
4
Кажется, это лучше, чем использовать, reset --hardпотому что он не перезаписывает ваши файлы (кроме тех, у которых проблемы слияния). Спасибо!
Синелав
Я пока не хотел разбивать файлы на файлы, поэтому добавил их - разве addсодержимое из рабочего дерева не попадает в индекс? Я не думаю, что я понимаю, почему ваш ответ работает из описания.
Дрю Ноакс
2
git addдействительно git resetставит их, но , что я делаю сразу же, unstages их. По сути, он очищает необработанные пути и возвращает меня к моему обычному рабочему дереву путем фальсификации мерзости.
Аарон
3
Вам не нужно, git addесли вы собираетесь git reset. В git resetэффективно «Отменяет» в git add. git reset( --mixed<- по умолчанию) фактически не затрагивает рабочий каталог, поэтому то, что было в вашем рабочем каталоге, конфликты слияния и все остальное, остается в покое. Хотя индекс (и технически HEADзаголовок ветви) сбрасывается (без ссылки, к которой они возвращаются , это, вероятно, означает отсутствие изменений для заголовка ветви и эффективно отменяет все, что было git addсделано с индексом, а также очищает состояние незаряженных путей) ,
Bambams
3
Последовательность , редактировать / решительность , git resetи git stash dropработает хорошо. Он делает то, git stash popчто сделал бы без конфликтов. Кажется, git addэто не нужно; хотя это может быть полезно, у вас есть много файлов с конфликтами. По мере того как каждый решается , их можно добавлять и git statusотслеживать их.
бесхитростный шум
13

Если, как и я, вам обычно требуется перезаписать содержимое рабочего каталога содержимым сохраненных файлов, но у вас все еще возникает конфликт, тогда вам нужно разрешить конфликт с помощью git checkout --theirs -- . корня.

После этого вы можете git resetперенести все изменения из индекса в рабочий каталог, поскольку, по-видимому, в случае конфликта изменения в несогласованных файлах остаются в индексе.

Вы также можете запустить git stash drop [<stash name>]после этого, чтобы избавиться от тайника, потому git stash popчто не удаляет его в случае конфликтов.

Педро Химено
источник
2

Обратите внимание, что Git 2.5 (2 квартал 2015 года) будущий Git может попытаться сделать этот сценарий невозможным.

См совершить ed178ef по Джефф Кинг ( peff), 22 апреля 2015.
(слиты Junio C Hamano - gitster- в фиксации 05c3967 , 19 мая 2015 года)

Примечание: это было отменено. Смотри ниже .

stash: требуется чистый индекс для применения / pop

проблема

Если вы stash apply/popпоместили содержимое в свой индекс и запустили « », мы можем столкнуться с конфликтом и добавить новые записи в индекс.
Восстановление в исходное состояние в этот момент затруднено, потому что такие инструменты, как «git reset --keep», сдувают все с места .

Другими словами:

" git stash pop/apply" забыл убедиться, что не только рабочее дерево чистое, но и индекс чистый.
Последнее важно, поскольку приложение-хранилище может конфликтовать, и индекс будет использоваться для разрешения конфликтов.

Решение

Мы можем сделать это более безопасным, отказавшись от применения при поэтапных изменениях.

Это означает, что если раньше были слияния из-за применения stash к измененным файлам (добавленным, но не зафиксированным), то теперь они не были бы слияниями, потому что stash apply / pop немедленно остановился бы с:

Cannot apply stash: Your index contains uncommitted changes.

Принудительное принятие изменений означает, что в случае слияний вы можете легко восстановить начальное состояние (до git stash apply/pop) с помощью git reset --hard.


См. Коммит 1937610 (15 июня 2015 г.) и коммит ed178ef (22 апреля 2015 г.) Джеффа Кинга ( peff) .
(Слиты Junio C Hamano - gitster- в фиксации bfb539b , 24 июня 2015)

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

К сожалению, это мешает некоторым распространенным рабочим процессам вокруг " git stash -k", например:

git add -p       ;# (1) stage set of proposed changes
git stash -k     ;# (2) get rid of everything else
make test        ;# (3) make sure proposal is reasonable
git stash apply  ;# (4) restore original working tree

Если вы «git commit» между шагами (3) и (4), то это просто работает. Однако, если эти шаги являются частью ловушки перед фиксацией, у вас нет такой возможности (вы должны восстановить исходное состояние независимо от того, пройдены тесты или нет).

VonC
источник