2012-01-25 2 views
19

Мы сделали что-то плохое.`git stash` во время конфликта слияния

Мы побежали git stash save во время конфликта слияния, и теперь мы не можем восстановить нашу работу.

Вещи, которые мы уже пробовали:

git pull -Xours origin master 
git stash apply --index 

И:

git pull origin master 
git stash save --keep-index "merge conflicts" 
git stash apply [email protected]{1} 

Пожалуйста, помогите!

+0

Вы действительно что-то значимое? (Вам действительно нужно восстановить спрятанные изменения?) Можете ли вы просто сбросить попытку слияния и сделать это снова? – Cascabel

+1

Да и нет, соответственно. Изменения состоят из более чем одного дня разрешения конфликтов слияния. – bukzor

+3

@ bukzor: Если вам нужно больше одного дня для разрешения конфликтов слиянием, возможно, пришло время пересмотреть свои политики в отношении обработки ветвей и распределения работы (или частоты слияния). Такие длительные разрешения слияния после этого являются хорошим источником труднодоступных ошибок из-за количества изменений, сделанных в одном коммите. – Grizzly

ответ

0

Когда вы находитесь в противоречивом состоянии (индекс и рабочий каталог), вы не сможете сделать git stash - это приведет к ошибке, содержащей непомеченные записи.

Убедитесь, что вы действительно сделали кошель. См выход git stauts и git stash show

+0

До 'git stash', я разрешил конфликты и продолжаю использовать' git add'. Это было после того, как я «git add» мои разрешения, я сделал дальнейшие изменения, а затем сделал «git stash save msg». Так что это удалось. –

+0

@ bukzor на самом деле, я просто проверил это с помощью msysgit 1.8.3 в Windows 7. Если файл оставлен конфликтующим (т. Е. Попытка разрешить конфликт слияния не была выполнена), тогда 'git stash save' действительно отменяется, без помещая конфликтный файл. Так что *** это на самом деле правильно, это не ложь ***. –

18

Проблема, кажется, что git stash не сохраняет ссылку на ветви, которую вы пытались объединить. Во время слияния, это хранится в исх имени MERGE_HEAD.

Чтобы исправить это и вернуться к предыдущему состоянию, необходимо найти пересмотр (давайте представим, что это d7a9884a380f81b2fbf002442ee9c9eaf34ff68d) вы пытаетесь объединить в, и установить MERGE_HEAD к нему после того, как вы примените тайник.

Затем вы можете применить тайник (с --index повторно сценическое все, что было до того поставил), и установите MERGE_HEAD:

git stash apply --index 
git update-ref MERGE_HEAD d7a9884a380f81b2fbf002442ee9c9eaf34ff68d 
+0

В то время как вышеизложенное кажется мне верным, я не совсем уверен, что просто установить MERGE_HEAD и разблокировать достаточно, чтобы восстановить статус слияния. Если бы это было возможно, я бы избежал использования git stash во время конфликтов. – user1338062

+1

Я бы тоже, но это задним числом на этом этапе. – bukzor

1

Учитывая ваш последний комментарий: Вы можете использовать

git stash megre --no-commit <branch> 

ставить индекс в «Объединить» состоянии без фиксации изменений

затем изменить его с тем, что вы хотите:

если вы уже разработали свой сливают в заначке:

git reset #to remove the "conflicts" flags 
git checkout <initial commit> -- ./ #to revert everything to the previous working state, 
git stash apply #apply your changes 

и сразу все в нужном состоянии, git commit


О комментарий bukzor «ы: есть на самом деле большой разница между git checkout <tree-ish> и git checkout <tree-ish> -- <files>.

Из reference на git checkout:

  • git checkout <branch>: Эта форма переключает ветвь путем обновления индекса, работая дерево, и ГЛАВНОЕ, чтобы отразить указанную ветвь или совершить.

  • git checkout [-p|--patch] <tree-ish> -- <pathspec>: Когда < пути > or --patch даны, git checkout не переключает ветви. Он обновляет именованные пути в рабочем дереве из индексного файла или с именем < tree-ish > (чаще всего это фиксация).

git checkout <initial commit> действительно отказался бы от информации о слиянии.

git checkout <initial commit> -- ./ (обратите внимание на дополнительные -- ./), с другой стороны, будет держать информацию о слиянии, и вернуть все гусеничный файл в состояние в <initial commit>.

+0

'git checkout' удалит состояние слияния, не так ли?В итоге у меня будет нормальная фиксация, которая объединит все изменения в главном. – bukzor

+0

'git stash apply' также очищает состояние слияния, явно устанавливая MERGE_HEAD ref, как было предложено в ответе Эвана, сделал трюк для меня –

+0

В git 2 нет такой команды, как' git stash merge' :( – dcorking

1

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

Во-первых, после того, как вы потеряли частичное слияние в ветке назначения, я захватил список файлов с оставшимися конфликтами (текстовый файл или вкладка редактора). Это всего лишь список неустановленных файлов после неустановления, так как файлы с конфликтами, которые были разрешены, были бы поставлены перед тем, как они будут скреплены.

$ git status 
# Changes not staged for commit: 
# (use "git add <file>..." to update what will be committed) 
# (use "git checkout -- <file>..." to discard changes in working directory) 
# 
# modified: myproject/src/main/java/com/acme/package3/Class3.java 
# modified: myproject/src/main/java/com/acme/package3/Class4.java 
# 

Далее, я создал патч и сбросить ветку обратно в состояние до слияния:

$ git diff HEAD > ~/merge-with-resolved-conflicts.patch 
$ git reset --hard HEAD 

Затем я создал временную ветвь (полученный из ветви слияния назначения), и применяется патч:

$ git checkout -b my-temp-branch 
$ git apply ~/merge-with-resolved-conflicts.patch 
$ git commit -a -m "Merge with resolved conflicts" 

Так ГОЛОВА моей-тЕМП-ветвь теперь содержит все, что было слито, в том числе файлов с конфликтами решенных и файлами с оставшимися конфликтами.

Затем я перешел обратно к исходной ветви, снова объединились, и посмотрел на статус мерзавца

$ git checkout my-branch 
$ git merge other-branch 
$ git status 

Статус показывает полный список файлов с конфликтами:

# Unmerged paths: 
# (use "git add <file>..." to mark resolution) 
# 
# both modified:  myproject/src/main/java/com/acme/package1/Class1.java 
# both modified:  myproject/src/main/java/com/acme/package2/Class2.java 
# both modified:  myproject/src/main/java/com/acme/package3/Class3.java 
# both modified:  myproject/src/main/java/com/acme/package3/Class4.java 
# 

Теперь мне нужно сравните эти два списка файлов. Любые файлы во втором списке, но не первый, уже были разрешены (в этом примере Class1.java и Class2.java). Таким образом, для каждого из этих файлов, я вытащил в версии с конфликтами решенных из временного отделения (например, вишни выбор, но для отдельных файлов, а не целой фиксации):

$ git checkout my-temp-branch myproject/src/main/java/com/acme/package1/Class1.java 
$ git checkout my-temp-branch myproject/src/main/java/com/acme/package2/Class2.java 

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

0

Мое решение выйти из этого (мерзавца копить поп во время слияния конфликта) было:

  • создать и оформить новый (локальный) филиал mytemporarybranch

    GIT филиал mytemporarybranch & & git checkout mytemporarybranch

  • совершить в этот mytemporarybranch

    мерзавец совершить -м "мой грязный слияние и сквош"

  • оформления заказа myoriginalbranch

    мерзавец фотографии myoriginalbranch

  • слияние правильно (не сквош поп/не применять этот раз!)

  • сквош объединить mytemporarybranch на ветви myoriginal

    мерзавца сливаться --squash mytemporarybranch

Смежные вопросы