Git에서 숨김 팝 중단


257

나는 숨어 있었고 병합 충돌이 발생했습니다. 중복으로 나열된 질문과 달리, 내가 유지하려는 디렉토리에 커밋되지 않은 변경 사항이 이미 있습니다. 병합 충돌을 사라지게하고 싶지 않고 팝 이전의 상태로 디렉토리를 다시 가져오고 싶습니다.

나는 시도 git merge --abort했지만 git은 병합이 진행 중이 아니라고 주장했다. 원래 디렉토리에서 변경 한 내용을 없애지 않고 팝을 중단하는 쉬운 방법이 있습니까?


커밋되지 않은 변경 사항에 대해서는 이러한 변경 사항이 이미 색인에 있었습니까?
jørgensen

사용중인 자식 버전을 게시 할 수 있습니까?
Tinman


2
허용 된 답변이 복잡해 보입니다. 나는 git stash pop부정한 일을 시도 하는 것과 같은 것을 결코하지 않는 것이 일반적으로 좋은 습관이라고 생각합니다 . 어떤 경우에도 간단하게 git reset --hard보관할 수 있습니다. (@BradKoch의 링크 된 주제가 제안하는 것 이상)
Steven Lu

1
@StevenLu, 나는 동의하지만 변경 사항을 다른 지점으로 옮기기 위해 변경 사항을 숨기면 문제가 깨끗하게 작동 할 수 있습니다. 숨김은 이전 분기에는 없었던 새 분기에 존재하는 커밋과 충돌합니다.
Jake Stevens-Haas

답변:


55

좋아, 나는 "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실패를 감안할 때 취소하려는 일부 작업이 완료되지 않았기 때문에 리버스도 실패 할 수 있다고 가정합니다.

다음은 작업 사본 (을 통해 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)

2
이 작업을 수행 한 후 이전에 저장된 편집 내용이 영구적으로 손실됩니까, 아니면 다시 숨김 상태입니까?
Brian H.

7
git stash apply은닉을 삭제하지 않으며, 병합이 실패한 경우 git stash pop에도 은닉을 유지합니다
Xerus

원래 숨김 팝 동안 병합 충돌이 있다면 나쁜 일이 일어날 것
3ocene

286

내 유스 케이스 : 잘못된 브랜치에 팝업을 시도하고 충돌이 발생했습니다. 필요한 것은 팝을 취소하지만 스 태시 목록에 유지하여 올바른 브랜치에서 팝 아웃하는 것입니다. 나는 이걸했다:

git reset HEAD --hard
git checkout my_correct_branch
git stash pop

쉬운.


22
당신이 원하는 숨김은 팝이 성공적으로 나올 때까지 숨김 목록에 남아 있습니까?
Ryan Clark

52
커밋되지 않은 로컬 변경 사항을 지우므로 원래 질문에 대한 답변이 아닙니다.
Dmitry

13
@RyanClark 아래 DavidG의 답변을 참조하십시오 . 기본적으로 그렇습니다. 숨김 목록에 있습니다.
fkorsa

1
이 상황에 처한 대다수의 사용자는이 솔루션이 이상적이라고 생각합니다. 작업 디렉토리를 변경하기 전에 커밋되지 않은 변경 사항이있는 상황을 상상할 수 없습니다 stash pop. 그것은 재난의 요리법처럼 들립니다.
Shadoninja

2
좋은. 이것을 읽은 후 git stash pop docs를 살펴본 후 "상태를 적용하면 충돌로 인해 실패 할 수 있습니다.이 경우 숨김 목록에서 제거되지 않습니다."라고 말합니다. 따라서 재설정 / 체크 아웃 후에 숨김을 다시 표시 할 수 있습니다.
브래디 홀트

48

편집 : git help stash팝 섹션 의 문서에서 :

상태를 적용하면 충돌로 실패 할 수 있습니다. 이 경우 숨김 목록에서 제거되지 않습니다. 수동으로 충돌을 해결하고 git stash drop을 수동으로 호출하십시오.

--index 옵션을 사용하면 작업 트리의 변경 사항뿐만 아니라 인덱스의 변경 사항도 복원하려고합니다. 그러나 충돌이있는 경우 (색인에 저장되어 원래 변경 사항을 더 이상 적용 할 수없는 경우) 실패 할 수 있습니다.

모든 저장소를 새 디렉토리에 하드 카피하여 사본을 작성하십시오.

git stash show 관심이 있다면 출력을 어딘가에 저장하십시오.

그런 다음 git stash drop충돌하는 숨김을 삭제하려면 다음을 수행하십시오.git reset HEAD

리포지토리를 이전 상태로 유지해야합니다 (아직도 여전히 문제를 재현 할 수 없었습니다)

===

문제를 재현하려고하지만 사용시 얻을 수있는 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

자식이 변경 사항을 병합하려고 시도하지 않고 실패합니다. 도움을주기 위해 수행 할 수있는 재현 단계가 있습니까?


다른 파일에 변경 사항을 보관하십시오.
asmeurer

다른 파일로 숨기려고 시도해도 작동하지 않습니다 (새로운 재현 단계 참조). 난 그냥 문제를 재현 할 수 없습니다 ...
DavidG

1
작업 디렉토리에 커밋되지 않은 변경 사항이 있으면이 솔루션이 작동하지 않습니다.
여기

@ 여기 이것은 실제 해결책이 아닙니다. 이것은 OP가 가진 문제를 재현 할 수 없으며 그가 어디에 있는지에 대한 단계를 제공하지 않았다는 것을 보여주기위한 것입니다.
DavidG

1
실제 시나리오는 다음과 같습니다. 1) 파일 A를 변경합니다. 2) 스 태쉬 변경 3) 파일 A에서 충돌을 변경하고 커밋 (예 : 동일한 행 변경) 4) 파일 B를 변경합니다. 5) 'git stash pop'을 수행합니다. 이제 충돌 및 로컬 변경 사항이 있습니다. 일반적으로 파일은 서로 다른 파일에 있지만 숨김에서 수정되지 않은 수정 된 파일과 스테이지되지 않은 로컬 변경 사항은 절대 알 수 없습니다.
Dmitry

16

나는 항상 사용했다

git reset --merge

나는 그것이 실패한 것을 기억할 수 없다.


@GauravPaliwal은, 그보고 다음 시간 I를 줄 것이다 git reset. 기능적으로 동일한 지 git reset --merge아십니까?
Kenn Sebesta

5

다른 변경 사항에 대해 걱정할 필요가없고 마지막 커밋으로 돌아가고 싶다면 다음을 수행하십시오.

git reset .
git checkout .
git clean -f

4

좋아, 나는 당신이 필요한 곳으로 돌아갈 수있는 워크 플로우를 찾았다 고 생각합니다 (팝을하지 않은 것처럼).

미리 백업하십시오! 이것이 당신에게 효과가 있는지 모르겠습니다. 그래도 효과가 없을 경우를 대비하여 전체 저장소를 복사하십시오.

1) 패치에서 발생하는 모든 변경 사항을 선택하여 병합 문제를 해결하고 모든 충돌을 수정하십시오 (rtotsemerge에서 이것은 하나의 REMOETE (그들의)로 나타납니다).

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^

간단한 예제를 통해 살펴 보았으므로 스 태쉬가 팝업되기 직전에 로컬 변경 사항과 스 태쉬를 계속 사용할 수있는 상태로 되돌릴 수 있습니다.


그것이 효과가 없다면, 대부분의 방법을 찾게 될 것입니다! :-)
agentgonzo

git stash show -p | git apply -Rgit stash apply실제 병합을 수행하면 작동하지 않습니다 . 내 답변보기 ...
Ben Jackson

3

나는 이것을 약간 다른 방식으로 해결했다. 여기에 일어난 일이 있습니다.

먼저 잘못된 브랜치에서 팝업이 발생하여 충돌이 발생했습니다. 숨김은 그대로 유지되었지만 색인은 충돌 해결에있어 많은 명령을 차단했습니다.

단순한 git reset HEAD분쟁 해결을 중단하고 커밋되지 않은 (및 원치 않는) ) 변경 사항을 .

몇몇 git co <filename>은 색인을 초기 상태로 되돌 렸습니다. 마지막으로 지점으로 전환 git co <branch-name>하고 new를 실행하여 git stash pop충돌없이 해결했습니다.


2

몇 가지 아이디어 :

  • git mergetool병합 파일을 원본과 새 부분으로 분할하는 데 사용 합니다. 바라건대 그 중 하나는 비스 태시 변경 사항이있는 파일입니다.

  • 이러한 변경 사항 만 취소하려면 숨김의 차이를 역으로 적용하십시오. 병합 충돌로 파일을 수동으로 분할해야 할 것입니다 (위의 트릭이 효과가 있기를 바랍니다).

나는 이들 중 하나를 테스트하지 않았으므로 그들이 작동하는지 확실하지 않습니다.


1

깨끗이 재현 할 수있었습니다 git stash pop커밋되지 않은 변경 사항을 사용하여 "더러운"디렉토리에서 를 있지만 아직 병합 충돌을 일으키는 팝은 없습니다.

경우 병합 충돌에 당신은 사라지지 않았다 적용하려고 숨김, 당신은 검사를 시도 할 수 있습니다 git show stash@{0}(선택적으로 --ours또는 --theirs)와 비교 git statis하고 git diff HEAD. 숨김을 적용하여 어떤 변경이 이루어 졌는지 확인할 수 있습니다.


1

병합 충돌로 인해 숨김이 발생하지 않은 DavidG가 올바른 경우 작업 디렉토리를 정리하기 만하면됩니다. 빠르게 git commit당신이 걱정하는 모든 것을. ( 완료하지 않으면 나중에 커밋 reset하거나 squash커밋 할 수 있습니다 .) 그런 다음 안전에 관심이있는 git reset모든 것과 git stash pop작업 디렉토리에 덤프 된 다른 모든 것을 사용 하십시오.


1

git stash pop질문에서와 같이 이전에 단계적 변경 사항이 없으면 다음 두 명령이 작동합니다.

git diff --name-only --cached | xargs git checkout --ours HEAD
git ls-tree stash@{0}^3 --name-only | xargs rm

첫 번째는 스 태쉬에서 병합 된 모든 것을 되돌립니다 (성공 여부). 두 번째는 숨김 파일에 의해 소개 된 추적되지 않은 파일을 삭제합니다.

From 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

나는 이것이 지금까지 가장 정답이라고 생각합니다. 잘 생각했습니다.
에이전트

0

git refloggit history에서 작성된 모든 변경 사항을 나열하는 데 사용하십시오 . 활동 ID 및 유형 복사git reset ACTION_ID


2
Git은 팝하기 전에 reflog 엔트리를 생성하지 않습니다 (커밋이 필요합니다)
Casebash

-1

다른 사람들이 내 대답이 도움이되기를 바랍니다. 내가 숨겨 놓은 지점과 다른 지점에서 숨김 팝을 시도 할 때 비슷한 문제가 발생했습니다. 내 경우에는 커밋되지 않은 파일이나 색인에 파일이 없지만 병합 충돌 사례 (@pid와 동일)에 여전히 도달했습니다. 다른 사람들이 이전에 지적했듯이 실패한 git stash pop은 실제로 내 숨김을 유지 한 다음 빠른 git reset HEAD 플러스 원래 분기로 돌아가서 거기에서 숨김을 수행하면 문제가 해결되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.