Git에서 오래된 (마지막이 아닌) 커밋에 변경된 파일을 추가하는 방법


461

지난 한 시간 동안 여러 가지 사항을 변경하고 단계별로 커밋했지만 일부 커밋 전에 변경된 파일을 추가하는 것을 잊어 버렸습니다.

로그는 다음과 같습니다.

    GIT TidyUpRequests u:1 d:0> git log 
    commit fc6734b6351f6c36a587dba6dbd9d5efa30c09ce 
    Author: David Klein <> 
    Date:   Tue Apr 27 09:43:55 2010 +0200

        The Main program now tests both Webservices at once

    commit 8a2c6014c2b035e37aebd310a6393a1ecb39f463 
    Author: David Klein <>
    Date:   Tue Apr 27 09:43:27 2010 +0200

        ISBNDBQueryHandler now uses the XPath functions from XPath.fs too

    commit 06a504e277fd98d97eed4dad22dfa5933d81451f 
    Author: David Klein <> 
    Date:   Tue Apr 27 09:30:34 2010 +0200

        AmazonQueryHandler now uses the XPath Helper functions defined in XPath.fs

    commit a0865e28be35a3011d0b6091819ec32922dd2dd8 <--- changed file should go here
    Author: David Klein <> 
    Date:   Tue Apr 27 09:29:53 2010 +0200

        Factored out some common XPath Operations

어떤 아이디어?


답변:


694

사용하십시오 git rebase. 구체적으로 특별히:

  1. git stash추가 할 변경 사항을 저장하는 데 사용하십시오 .
  2. 사용하십시오 git rebase -i HEAD~10(그러나 많은 커밋을 원합니다).
  3. 줄의 시작 부분에서 a0865...단어 pick를 로 변경하여 해당 커밋 ( )을 편집 할 수 있도록 표시하십시오 edit. 커밋이 삭제되므로 다른 줄은 삭제하지 마십시오. [^ vimnote]
  4. rebase 파일을 저장하면 git은 쉘로 다시 돌아가서 커밋을 수정하기를 기다립니다.
  5. 를 사용하여 숨김을 팝 git stash pop
  6. 로 파일을 추가하십시오 git add <file>.
  7. 로 커밋을 수정하십시오 git commit --amend --no-edit.
  8. DO가 git rebase --continue새에 대해 커밋의 나머지 부분을 다시 할을.
  9. 편집을 위해 둘 이상의 커밋을 표시 한 경우 2 단계부터 반복하십시오.

[^ vimnote] : 당신이 사용하는 경우 vim다음 명중 할 것이다 Insert다음, 편집에 키 Esc에서 입력 한 :wq파일을 저장 편집기를 종료하고 변경 사항을 적용 할 수 있습니다. 또는을 사용하여 사용자 친화적 인 git commit 편집기구성 할 수 있습니다git config --global core.editor "nano" .


23
편집에 추가 할 단계적 변경 사항이없는 경우 어떻게해야합니까? 내가 그들을 숨기고, 내가 할 수 없었다 git add.
Sam

15
샘 당신은 단순히 커밋하는 동안 변경 사항을 취소 할 수 있습니다.
omnikron

17
참고 :로 edit커밋을 표시하면 파일에 나열된 다른 커밋을 삭제하지 마십시오. 그렇게하면 커밋이 삭제되고 다시 커밋 하려면 다음 단계따라야 합니다.
David Tuite

2
@DavidTuite가 말한 것과 관련하여, git에서 물건을 할 때 내 습관은 어떻게 될지 잘 모르겠습니다. 일을 망칠 경우 타임 라인의 현재 상태를 저장하는 "branchname-ref"분기를 만드는 것입니다. 완료되면 삭제합니다.
Raphael

1
6 단계에서을 포함하십시오. 명령에서 (점). 올바른 명령 :git add .
Tom

323

이전 커밋의 커밋 메시지를 변경하지 않고 작은 변경으로 기존 커밋을 "수정"하려면 OLDCOMMIT다음과 같습니다 091b73a.

git add <my fixed files>
git commit --fixup=OLDCOMMIT
git rebase --interactive --autosquash OLDCOMMIT^

git commit --squash=OLDCOMMIT리베이스 중에 이전 커밋 메시지를 편집하는 데 사용할 수도 있습니다 .


  • git rebase --interactiverebase 명령어 순서 를 확인 (또는 편집) 하기 위해 텍스트 편집기 (구성 할 수 있음 )를 불러옵니다 . 파일 에 rebase 명령어 변경에 대한 정보 가 있습니다. 바로 저장하고 종료 (에디터 에서 REBASE를 계속 참조).:wqvim
  • --autosquash--fixup=OLDCOMMIT커밋을 원하는 순서대로 자동으로 배치합니다 . 참고 --autosquash경우에만 유효한 --interactive옵션이 사용됩니다.
  • ^OLDCOMMIT^의인 전에 커밋에 수단이 참조입니다 OLDCOMMIT.

위의 단계는 rebase 명령 시퀀스 를 확인 및 / 또는 수정하는 데 유용 하지만 다음과 같이 대화 형 rebase 텍스트 편집기를 건너 뛰거나 자동화 할 수도 있습니다.

git commitgit rebase를 참조하십시오 . 항상 git history를 다시 작성할 때는 아직 다른 사람 (임의의 인터넷 사용자 및 빌드 서버 포함)에게 게시하지 않은 커밋 만 수정해야합니다.


18
다른 옵션보다 훨씬 명확하고 매력처럼 작동했습니다.
Chris Mitchelmore

5
@Jonah : 커밋 메시지 를 편집하기 위해 편집기를 열지 않고 rebase 단계 를 확인 (또는 편집) 합니다 . 피할 수 없습니다. 옵션을 사용하는 --autosquash경우에만 유효합니다--interactive .
Joel Purra

5
이 솔루션을 사용하여 VIM을 표시하는 자식이 붙어 있습니다. 내 문제는 VIM을 사용하는 방법을 모른다는 것입니다. 도대체 어떻게 빠져 나가고, 이것을 어떻게 제어 할 수 있습니까?
Neon Warge

2
@NeonWarge : 선택한 편집기는 예를 들어을 사용하여 구성 할 수 git config --global core.editor "pico"있습니다. 있습니다 시스템의 기본 편집기 변경 구성 자식 및 / 또는 여러 가지 다른 방법 등등은.
Joel Purra

2
한 줄 좋은 별칭은 여기
idanp

61

git 1.7에서는 다음을 사용하는 정말 쉬운 방법이 있습니다 git rebase.

파일 준비 :

git add $files

새로운 커밋을 만들고 "깨진"커밋의 커밋 메시지를 재사용

git commit -c master~4

fixup!제목 줄 앞에 추가 하거나 squash!커밋 (메시지)을 편집하려는 경우 :

fixup! Factored out some common XPath Operations

git rebase -i --autosquash커밋을 수정 하는 데 사용


2
+1. 새로운 픽스 업 지시어 (1.7+) 사용 : stackoverflow.com/questions/2302736/trimming-git-checkins/…
VonC

@ knittl 나는 내 파일의 오래된 커밋 (푸시되지 않은)에 다른 파일을 추가하기 위해 메소드를 시도했지만 rebasing 할 때 You asked me to rebase without telling me which branch you want to rebase against, and 'branch.master.merge'나는 그것을 사용 git rebase -i --autosquash하면 noop제목 줄을 얻고 커밋을 rebasing합니다. 내가 뭘 잘못했는지 알아?
oschrenk

7
@oschrenk : 예를 들어 rebase하려는 커밋을 제공해야합니다. 예 :git rebase -i --autosquash HEAD~10
knittl

1
좋은 답변이지만 리베이스 할 커밋을 추가해야했습니다. 업데이트 할 수 있다면 좋을 것입니다.
Paul Odeon

@PaulOdeon : 귀하의 질문을 이해하지 못합니다. 무엇을하려고합니까? 어디에서 문제가 있습니까?
knittl

8

rebase --interactive이전 커밋을 수정하기 위해 세션을 시도 할 수 있습니다 ( 이 커밋을 다른 리포지토리로 푸시하지 않은 경우 ).

때때로 b.2에서 수정 된 것. 이 커밋은 패치 시리즈에 깊이 묻혀 있기 때문에 수정되지 않은 완벽한 커밋으로 수정할 수 없습니다 .
이것이 바로 대화식 리베이스의 목적입니다. 커밋을 재 배열하고 편집하고 여러 커밋을 하나로 스 쿼싱하여 많은 "a"와 "b"후에 사용하십시오.

그대로 유지하려는 마지막 커밋으로 시작하십시오.

git rebase -i <after-this-commit>

주어진 커밋 뒤에 오는 현재 분기의 모든 커밋 (병합 커밋 무시)으로 편집기가 시작됩니다.
이 목록의 커밋을 마음의 내용으로 재정렬하고 제거 할 수 있습니다. 목록은 다음과 같이 다소 비슷합니다.

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

oneline 설명은 순전히 당신의 즐거움을위한 것입니다. git rebase는 커밋 이름 (이 예제에서는 "deadbee"및 "fa1afe1")을 보지 않으므로 이름을 삭제하거나 편집하지 마십시오.

"pick"명령을 "edit"명령으로 대체하면 커밋을 적용한 후 git rebase에게 중지하도록 지시하여 파일 및 / 또는 커밋 메시지를 편집하고 커밋을 수정 한 후 rebasing을 계속할 수 있습니다.

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