git에서 비 단계적 변경의 일부를 취소


158

git에서 스테이지되지 않은 변경 사항의 일부를 실행 취소하지만 나머지는 스테이지되지 않은 상태로 유지하려면 어떻게합니까? 내가 알아 낸 방법은 다음과 같습니다.

git commit --interactive
# Choose the parts I want to delete
# Commit the changes
git stash
git rebase -i master # (I am an ancestor of master)
# Delete the line of the most recent commit
git stash apply

이것은 효과가 있지만 git commit --interactive변경 사항을 되 돌리는 것과 같은 것이 있으면 좋을 것 입니다. 더 나은 방법이 있습니까?

답변:


264

당신은 사용할 수 있습니다 git checkout -p당신은 되돌리기에 작업 카피와 지수 사이의 DIFF에서 개별 심술쟁이를 선택할 수있는. 마찬가지로, git add -p인덱스에 추가 할 덩어리를 선택할 git reset -p수 있으며 인덱스와 HEAD 사이의 차이에서 인덱스에서 제거 할 개별 덩어리를 선택할 수 있습니다.

$ git checkout -p file/to/partially/revert
# or ...
$ git checkout -p .

이러한 변경 사항을 되돌리기 전에 보존하기 위해 git 저장소를 미리 스냅 샷하려면 다음과 같이하십시오.

$ git stash; git stash apply

자주 사용한다면 별명을 지정할 수 있습니다.

[alias]
    checkpoint = !git stash; git stash apply

좋은 편집기 모드 또는 플러그인을 사용하면 개별 덩어리 또는 줄을 쉽게 되돌릴 -p수 있습니다.이 옵션은 때때로 사용하기가 약간 어색 할 수 있으므로 되돌릴 줄을 직접 선택할 수 있습니다. Git 작업에 매우 유용한 Emacs 모드 인 Magit을 사용 합니다. Magit에서을 실행 magit-status하고 되돌릴 변경 사항의 차이점을 찾고 되돌릴 줄을 선택하십시오 (또는 한 번에 덩어리를 되 돌리지 않으려면 되돌릴 덩어리에 커서를 두십시오) 한 번에 한 줄씩)을 눌러 k해당 특정 줄을 되돌립니다. Emacs를 사용한다면 Magit을 강력히 추천합니다.


나는 이것이 원래 생각해 낸 솔루션만큼 복잡하다고 생각하지만, 원래 솔루션은 제거 된 라인이 커밋되어 30 일 동안 절약 할 수 있다는 이점이 있다고 생각합니다. 그래도 쉘 스크립트를 작성하는 것이 좋을 것이라고 생각합니다.
asmeurer

1
죄송합니다 . 단일 명령으로 요청한 것과 정확히 일치 git checkout하는 -p플래그 도 있음을 깨달았습니다 . 이전 단계의 복잡한 단계에 대한 사과 당신은 그냥 사용할 수 있습니다 git checkout -p. 물건을 저장하는 한, 잠재적으로 파괴적인 일을하기 전에 나는 현재 나무를 숨김으로 기록하기 위해 종종 git stash; git stash apply(또는 별명으로 만드는 별명을 작성 git checkpoint) 무언가 잘못되면 다시 얻을 수 있습니다.
Brian Campbell

당신이 간다, 그것이 해결책이다! 별명에 관해서는, 나는 git commit -a -m "Backup Commit" --edit; git reset HEAD^ 그것이 더 좋은 것으로 생각하고 있습니다. 왜냐하면 그것은 내 숨김 상태를 더럽 히지 않을 것입니다. 그런 다음 SHA1이 있으면 다음 30 일 이내에 체리 픽을 선택할 수 있습니다. --edit를 사용하면 나중에 원하는 경우 SHA1을 찾는 데 도움이되는 정보를 커밋 메시지에 추가 할 수 있습니다. 반면에, 이것은 git reflog를 더럽힐 것이므로, 당신이하는 일에 기반한 트레이드 오프라고 생각합니다.
asmeurer

검사 점 별칭이 작동하지 않습니다. 두 번째 명령이 아닌 첫 번째 명령 만 실행됩니다. 내가 그것을 좋아했을 것이기 때문에 슬프다. git 버전 1.7.10.4를 사용하고 있습니다.
Fabien

git checkout -p패치를 인덱스에 적용하지 않고 스테이징 만하 는 방법이 있습니까?
Geremia

28
git diff > patchfile

그런 다음 패치 파일을 편집하고 실행 취소하지 않으려는 부분을 제거하십시오.

patch -R < patchfile

6
그러나이 답변은 단순성과 사용 편의성면에서 특히 훌륭합니다. +1
15:14:59

생성 patchfile된 vim에서 멋지게 보이고 정말 도움이됩니다!
Bily

완전한. Cygwin 및 Windows 용 Ubuntu bash가있는 Windows에서도 작동하는지 확인할 수 있습니다.
Checo R

1
git apply -R대신에 대신 사용할 수도 있습니다 patch(git 영역 내에서 또는 patch사용
불가능한 다른 상황에 머무르기 위해

patch: **** malformed patch at line 41: @@ -428,9 +443,9 @@ you should place your code here."
HappyFace

5

넌 할 수있어

git checkout master -- path/to/file

재설정하려는 각 파일마다.


또는 지점에서 작업하는 경우 마스터 대신 HEAD를 사용하십시오. 'git status'보고서에 나와 있듯이 (최소 최신 버전에서는).
Jonathan Leffler

1

어때요?

  1. 색인의 변경 사항으로 영향을받는 파일을 제거하십시오.
  2. git add -p색인에 원하는 변경 사항 만 다시 추가 하는 데 사용 하십시오.

1

'git status'를 실행하면 다음과 같이 표시됩니다.

$ git status
# On branch fr/fr.002
# 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:   makefile
#
no changes added to commit (use "git add" and/or "git commit -a")
$

따라서 스테이지되지 않은 편집을 취소하려면 다음을 실행하라는 메시지가 표시됩니다.

git checkout -- makefile

3
그는 한 번에 전체 파일이 아닌 개별 덩어리를 되 돌리는 방법에 대해 궁금해하고 있다고 생각합니다. 물론 파일의 모든 변경 사항을 취소 해야하는 경우 솔루션입니다.
Brian Campbell

예-당신이 맞다고 생각합니다. 'git checkout -p'및 'git add -p'옵션은 원하는 것처럼 보입니다.
Jonathan Leffler

1

Brian Campbell의 대답은 알 수없는 이유로 내 자식 버전 1.9.2.msysgit.0과 충돌하므로 내 접근 방식은 유지하려는 덩어리를 스테이징하고 작업 사본의 변경 사항을 버린 다음 무대를 비우는 것입니다.

$ git add -p
   ... select the hunks to keep
$ git checkout -- .
$ git reset HEAD .

1
또한 있습니다 git stash -p. 당신은 할 수 있습니다 git stash -p; git reset --hard; git stash pop. 이것은 커밋 메시지를 작성할 필요가 없다는 점을 제외하고는 실제로 수행하는 것과 동일합니다.
asmeurer

@asmeurer는 건배. 광산에는 커밋 메시지가 필요하지 않지만 인덱스보다 숨김을 사용하는 것이 더 합리적입니다.
G-Wiz

0

당신이 할 수있는 git checkout그것을 실행 취소 할 부품의 이름을 이름을 제공합니다.

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