Прерывание тайника поп в Git



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



пробовал git merge --abort, но git утверждал, что слияние не происходит. Есть ли простой способ прервать поп, не разрушая изменения, которые я изначально имел в справочник?

698   12  

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 apply failed я предполагаю, что обратное также может потерпеть неудачу, так как некоторые из вещей, которые он хочет отменить, не были выполнены.

вот пример, показывающий, как рабочая копия (через 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 mergetool

2) совершить эти изменения (они уже будут добавлены с помощью команды mergetool). Дайте ему сообщение о фиксации "слияния" или что-то, что вы помните.

git commit -m "merge"

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

git add .
git add -u .
git commit -m "local changes"

4) обратный патч. Это можно сделать с помощью следующей команды:

git stash show -p | git apply -R

5) совершать эти изменения:

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

    Ничего не найдено.