Прерывание тайника поп в Git
Я выскочил тайник и был конфликт слияния. В отличие от вопроса, который указан как дубликат, у меня уже были некоторые незафиксированные изменения в каталоге, который я хотел сохранить. Я не просто хочу, чтобы конфликт слияния исчез, но и вернуть мой каталог в состояние, в котором он был до поп-музыки.
пробовал git merge --abort, но git утверждал, что слияние не происходит. Есть ли простой способ прервать поп, не разрушая изменения, которые я изначально имел в справочник?
12 ответов:
хорошо, я думаю, что я разработал "git stash unapply". Это сложнее, чем
git apply --reverseпотому что вам нужно обратное действие слияния в случае, если было какое-либо слияние сделаноgit stash apply.обратное слияние требует, чтобы все текущие изменения были помещены в индекс:
git add -uзатем инвертируем
merge-recursiveчто было сделаноgit stash apply:
git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1теперь у вас останется только не-тайник меняется. Они будут в индексе. Вы можете использовать
git resetчтобы отменить изменения, если хотите.учитывая, что ваш оригинальный
git stash applyfailed я предполагаю, что обратное также может потерпеть неудачу, так как некоторые из вещей, которые он хочет отменить, не были выполнены.вот пример, показывающий, как рабочая копия (через
git status) заканчивается снова чистым:$ git status # On branch trunk nothing to commit (working directory clean) $ git stash apply Auto-merging foo.c # On branch trunk # Changed but not updated: # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: foo.c # no changes added to commit (use "git add" and/or "git commit -a") $ git add -u $ git merge-recursive stash@{0}: -- $(git write-tree) stash@{0}^1 Auto-merging foo.c $ git status # On branch trunk nothing to commit (working directory clean)
мой вариант использования: просто попытался выскочить на неправильную ветку и получил конфликты. Все, что мне нужно, это отменить pop, но сохранить его в списке тайников, чтобы я мог вытащить его на правильную ветку. Я сделал это:
git reset HEAD --hard git checkout my_correct_branch git stash popлегко.
Edit: From the
git help stashдокументация в разделе pop:применение состояния может завершиться неудачей с конфликтами; в этом случае оно не удаляется из списка тайников. Вам нужно решить конфликты вручную и вызвать git stash drop вручную после этого.
если используется параметр --index, то пытается восстановить не только изменения рабочего дерева, но и изменения индекса. Однако, это может не сработать, если у вас есть конфликты (которые хранятся в индексе, где вы поэтому больше не может применять изменения, как они были первоначально).
попробуйте скопировать все ваше РЕПО в новый каталог (так что у вас есть его копия) и запустите:
git stash showи сохраните этот вывод где-нибудь, если вы заботитесь об этом.затем:
git stash dropконфликт заначку затем:git reset HEADэто должно оставить ваше РЕПО в том состоянии, в котором оно было раньше (Надеюсь, я все еще не смог упрекнуть вашу проблему)
===
Я пытаясь упрекнуть вашу проблему, но все, что я получаю, когда usin
git stash pop- это:error: Your local changes to the following files would be overwritten by merge: ... Please, commit your changes or stash them before you can merge. Abortingв чистом реж:
git init echo hello world > a git add a & git commit -m "a" echo hallo welt >> a echo hello world > b git add b & git commit -m "b" echo hallo welt >> b git stash echo hola mundo >> a git stash popЯ не вижу, как git пытается объединить мои изменения, он просто терпит неудачу. У вас есть какие-либо шаги по повторению, которые мы можем выполнить, чтобы помочь вам?
Если вам не нужно беспокоиться о каких-либо других изменениях, которые вы сделали, и вы просто хотите вернуться к последней фиксации, то вы можете сделать:
git reset . git checkout . git clean -f
хорошо, я думаю, что мне удалось найти рабочий поток, который вернет вас туда, где вам нужно быть (как будто вы не сделали поп).
СДЕЛАЙТЕ РЕЗЕРВНУЮ КОПИЮ ЗАРАНЕЕ!! Я не знаю, сработает ли это для вас, поэтому скопируйте все свое РЕПО на случай, если оно не сработает.
1) исправьте проблемы слияния и исправьте все конфликты, выбрав все изменения, которые приходят из патча (в tortoisemerge это отображается как одно.РЕМОЕТЕ (их)).
git mergetool2) совершить эти изменения (они уже будут добавлены с помощью команды mergetool). Дайте ему сообщение о фиксации "слияния" или что-то, что вы помните.
git commit -m "merge"3) Теперь у вас все еще будут ваши локальные нестагированные изменения, которые вы начали изначально, с новой фиксацией из патча (мы можем избавиться от этого позже). Теперь совершить свой неиндексированных изменений
git add . git add -u . git commit -m "local changes"4) обратный патч. Это можно сделать с помощью следующей команды:
git stash show -p | git apply -R5) совершать эти изменения:
git commit -a -m "reversed patch"6) избавиться от патч/убрать изменения, внесенные заплатами совершает
git rebase -i HEAD^^^из этого удалите две строки с "слиянием" и "обратным патчем" в нем.
7) верните свои неназванные изменения и отмените фиксацию "локальных изменений"
git reset HEAD^я пробежался по нему с простым примером, и он возвращает вас туда , где вы хотите быть-непосредственно перед тем, как тайник был выскочил, с вашими локальными изменениями и с тайником, который все еще доступен поп.
Я решил это несколько по-другому. Вот что случилось.
во-первых, я выскочил на неправильной ветке и получил конфликты. Тайник остался нетронутым, но индекс был в разрешении конфликта, блокируя многие команды.
простой
git reset HEADпрервал разрешение конфликта и оставил незафиксированным (и нежелательного) изменения.несколько
git co <filename>вернул индекс в исходное состояние. Наконец, я переключил ветку сgit co <branch-name>и запустить новыйgit stash pop, которые решить без конфликтов.
некоторые идеи:
использовать
git mergetoolдля разделения файлов слияния на исходные и новые части. Надеюсь, один из них-это файл с вашими изменениями без тайника в нем.примените разницу в тайнике в обратном порядке, чтобы отменить только эти изменения. Вам, вероятно, придется вручную разделить файлы с конфликтами слияния (что, надеюсь, сработает для вышеприведенного трюка).
Я не тестировал ни один из них, так что я не делаю знаю точно, что они будут работать.
использовать
git reflogчтобы перечислить все изменения, внесенные в историю git. Скопируйте идентификатор действия и введитеgit reset ACTION_ID
я мог бы воспроизвести чистый
git stash popв" грязном " каталоге, с незафиксированными изменениями, но еще не поп, который генерирует конфликт слияния.если при конфликте слияния тайник, который вы пытались применить, не исчез, вы можете попробовать изучить
git show stash@{0}(опционально с--oursили--theirs) и сравниваем сgit statisиgit diff HEAD. Вы должны быть в состоянии видеть, какие изменения произошли от применения тайника.
если DavidG правильно, что он не поп тайник из-за конфликта слияния, то вам просто нужно очистить свой рабочий каталог. Быстро
git commitвсе, что вас волнует. (Вы можетеresetилиsquashфиксация позже, если вы не сделали.) Тогда со всем, что вы заботитесь о безопасности,git resetвсе остальное, чтоgit stash popсбрасывается в ваш рабочий каталог.
если не было никаких поэтапных изменений перед
git stash pop, как в вопросе, то следующие две команды должны работать.git diff --name-only --cached | xargs git checkout --ours HEAD git ls-tree stash@{0}^3 --name-only | xargs rmпервый отменяет любые слияния из тайника, успешные или нет. Второй удаляет все неотслеженные файлы, введенные тайником.
С
man git stash:The working directory must match the index.который @DavidG указывает,stash popпроизойдет сбой, если какие-либо в настоящее время неустановленные измененные файлы конфликтуют. Таким образом, нам не нужно беспокоиться о расплетении конфликтов слияния за пределами возвращения кHEAD. Любые оставшиеся измененные файлы не связаны с тайником и были изменены доstash popесли бы были поэтапные изменения, мне неясно, можем ли мы полагаться на те же команды, и вы можете попробовать технику @Ben Jackson. Предложения приветствуются..
вот тестовая установка для всех различных случаев https://gist.github.com/here/4f3af6dafdb4ca15e804
# Result: # Merge succeeded in m (theirs) # Conflict in b # Unstaged in a # Untracked in c and d # Goal: # Reverse changes to successful merge m # Keep our version in merge conflict b # Keep our unstaged a # Keep our untracked d # Delete stashed untracked c
Я публикую здесь, надеясь, что другие мои считают мой ответ полезным. У меня была аналогичная проблема, когда я пытался сделать тайник поп на другой ветке, чем тот, который я спрятал. В моем случае у меня не было файлов, которые были незафиксированы или в индексе, но все же попали в случай конфликтов слияния (тот же случай, что и @pid). Как указывали другие ранее, неудачный git stash pop действительно сохранил мой тайник, а затем быстрый git reset HEAD plus вернулся к моей оригинальной ветке и сделал тайник оттуда это решило мою проблему.
Comments