Git에서 파일의 일부만 커밋


2764

Git에서 파일을 변경할 때 일부 변경 사항 만 커밋하려면 어떻게해야합니까?

예를 들어, 파일에서 변경된 30 줄 중 15 줄만 어떻게 커밋 할 수 있습니까?


3
관련 stackoverflow.com/q/34609924/52074 : 덩어리를 작은 덩어리로 분할 해야하는 경우.
Trevor Boyd Smith

요약 : 기능면에서 : git gui= git add -e> git add -i -p; 편의성 측면에서 : git gui> git add -i -p> git add -e. 따라서 : git guiX에 액세스 할 때 선택 git add -i -p하십시오. 간단한 항목을 선택하고 X 를 사용 git add -e하지 않고 복잡한 스테이징에 X를 사용하지 않거나 사용하지 않으려는 경우 선택하십시오.
Penghe Geng

답변:


3687

당신은 git add --patch <filename>(또는 -p짧게) 사용할 수 있으며 , git은 파일을 합리적인 "hunks"(파일의 일부)라고 생각하는 것으로 파일을 나누기 시작합니다. 그런 다음이 질문을 묻습니다.

Stage this hunk [y,n,q,a,d,/,j,J,g,s,e,?]?

각 옵션에 대한 설명은 다음과 같습니다.

  • y 다음 커밋을 위해이 덩어리를 준비하십시오
  • n 다음 커밋을 위해이 덩어리를 준비하지 마십시오
  • q떠나다; 이 덩어리 또는 나머지 덩어리를 준비하지 마십시오
  • a 파일에서이 덩어리와 모든 이후 덩어리를 준비하십시오.
  • d 파일에서이 덩어리 또는 이후 덩어리를 스테이징하지 마십시오.
  • g 갈 덩어리를 선택하십시오
  • / 주어진 정규식과 일치하는 덩어리를 검색
  • j 이 덩어리를 미결정 상태로 두십시오. 다음 미정 덩어리를 참조하십시오.
  • J 이 덩어리를 미정의 상태로 두십시오, 다음 덩어리를보십시오
  • k 이 덩어리를 미정의 상태로 두십시오.
  • K 이 덩어리를 미정의 상태로 두십시오, 이전 덩어리를보십시오
  • s 현재 덩어리를 작은 덩어리로 나누십시오
  • e 현재 덩어리를 수동으로 편집
  • ? 덩어리 도움말 인쇄

파일이 아직 저장소에없는 경우 먼저 할 수 있습니다 git add -N <filename>. 이후에 계속할 수 있습니다 git add -p <filename>.

이후에는 다음을 사용할 수 있습니다.

  • git diff --staged 올바른 변경을 수행했는지 확인
  • git reset -p 실수로 추가 된 덩어리를 스테이지 해제하기 위해
  • git commit -v 커밋 메시지를 편집하는 동안 커밋을 봅니다.

이것은 git format-patch커밋 데이터를 .patch파일 로 구문 분석 하는 명령과 는 매우 다릅니다 .

미래를위한 참조 : Git Tools-Interactive Staging


83
유용한 대화식 모드 를 시작하는 명령 -p/--patch내부의 패치 작업에 대한 바로 가기 라는 점에 유의하는 것이 좋습니다. -i/--interactive
tutuDajuju

5
> 파일이 이미 준비된 경우 어떻게됩니까? 스테이지되지 않은 변경 사항 만 표시됩니다. 그렇습니다 git diff.
Eugen Konkov 2016 년

3
현재 덩어리를 수동으로 편집하려면 어떻게해야합니까? e를 입력 한 후 어떻게해야할지 모르겠습니다.
Hunsu

23
버튼을 누른 후 e, 수동으로 교체하여 덩어리를 편집 할 수 있습니다 +또는 -의해#
veksen

1
이것은 훌륭하지만 지금은 실제로 어떻게 밀어 넣습니까? 내가 git push이미 최신 상태라고 말합니다. 내가하면 git diff내가 말한 덩어리를 볼 n수 있습니다. 내가 git diff --staged저지른 커밋을 볼 수 있다면 커밋을 푸시 할 수 있다고 가정하면 내가 말한 덩어리를 어떻게 삭제 no합니까?
chovy 2016 년

250

당신은 사용할 수 있습니다 git add --interactive또는 다음과 ( 하지 ); git-add 맨 페이지의 대화식 모드 를 참조 하거나 지침을 따르십시오.git add -p <file>git commit git commit -a

현대 망할 놈도있다 git commit --interactive(그리고 git commit --patch대화 형 커밋에서 패치 옵션 바로 가기된다).

GUI에서 선호하는 경우 git-gui를 사용할 수 있습니다 . 커밋에 포함하려는 청크를 간단히 표시 할 수 있습니다. 개인적으로 사용하는 것보다 쉽습니다 git add -i. QGit 또는 GitX와 같은 다른 git GUI에도이 기능이있을 수 있습니다.


1
흥미롭게도 windows.github.com은 부분 파일 커밋을 지원했지만 최근에이를 중단 한 것으로 보입니다.
Juri

1
@Juri 부분 파일 커밋에 대한 지원이 다시 시작되었다고 생각합니다.
Ela782

@Juri 천만에요. 나는 실제로 그것이 이전에 거기에 있었다는 것을 눈치 채지 못했습니다. 나는 지난주에 그것을보고 "아, 정말 놀라운 새 기능"이라고 생각했습니다! :-)
Ela782

1
요즘 windows.github.com은 Git GUI보다 더 훌륭하고 부분 커밋을 지원하지만 브랜드 커밋 서명은 지원하지 않는 새로운 브랜드의 GitHub Desktop으로 리디렉션합니다. 한숨.

147

git gui 는 diff보기에서이 기능을 제공합니다. 관심있는 행을 마우스 오른쪽 단추로 클릭하면 "이 행을 커밋하여 스테이지"메뉴 항목이 표시됩니다.


13
복잡한 패치의 경우 일반적으로 가장 빠른 방법입니다.
hochl

7
이는 스테이징 영역에 미세한 방식으로 변경 사항을 추가 할 수있는 매우 효율적이고 직관적 인 방법입니다. 또한 여러 줄을 선택할 수 있으며 해당 선택 내의 모든 변경 사항이 추가됩니다.
jox

이것은 gitk아니지만 Windows 용 Git Bash에 포함되어 있습니다. 시작 메뉴 항목이 있거나 명령을 사용하여 시작할 수 있습니다 git gui. 또한 stage this hunk어느 것보다 유용 할 것 stage this line입니다. 이 답변이 10 년 전에 만들어진 이후로 새로운 것일 수 있습니다.
Chris

82

git add -e myfile텍스트 편집기를 열고 스테이지하고 싶은 줄과 원하지 않는 줄을 선택할 수 있기 때문에 이것이 가장 쉬운 방법 이라고 생각합니다 . 편집 명령과 관련하여 :

추가 된 내용 :

추가 된 내용은 "+"로 시작하는 줄로 표시됩니다. 추가 라인을 삭제하여 스테이징을 방지 할 수 있습니다.

제거 된 내용 :

제거 된 내용은 "-"로 시작하는 줄로 표시됩니다. "-"를 ""(공백)으로 변환하여 제거가 준비되지 않도록 할 수 있습니다.

수정 된 내용 :

수정 된 내용은 "-"줄 (이전 내용 제거)과 "+"줄 (대체 내용 추가)로 표시됩니다. "-"행을 ""로 변환하고 "+"행을 제거하면 수정 사항이 스테이징되지 않도록 할 수 있습니다. 쌍의 절반 만 수정하면 색인이 혼동 될 수 있습니다.

에 대한 모든 세부 정보 git addgit --help add


7
이 줄을 실제로 선택하는 방법에 대한 명확한 설명이있는 경우 (예 : 입력 할 실제 명령) 더 유용합니다. 설명서에서 찾을 수 없습니다. 참조를 추가 할 수 있습니까?
Alex

4
속기 옵션을 좋아하지 않는 사람들에게는 -e입니다 --edit.
Kolyunya

2
에서 섹션 편집 패치 출신 theFreedomBanana 추가 참조 인용 @ 알렉스git --help add
랜달

8
이것은 s대화식 패치 모드에서 덩어리를 작게 만들 수 없을 때 줄을 현명하게 추가 / 제거하는 문제를 해결하는 유일한 대답 (git 만 필요)입니다 .
cdosborn

3
이 명령 ( git add -e)은 디스크의 파일 내용을 변경하지 않는다는 것을 이해하는 것이 도움이 될 수 있습니다 . 변경 사항 중 일부를 비 스테이지에서 스테이징 (인덱스)으로 이동합니다.
Penghe Geng

44

vim을 사용하는 경우 fugitive 라는 훌륭한 플러그인을 사용해보십시오 .

을 사용하여 작업중인 복사와 색인간에 파일의 차이점을 볼 수 있으며 :Gdiff, 다음과 같은 고전적인 vim diff 명령을 사용하여 색인에 줄이나 덩어리를 추가 할 수 dp있습니다. 색인에 수정 사항을 저장하고로 커밋 :Gcommit하면 완료됩니다.

여기에 아주 좋은 소개 스크린 캐스트가 있습니다 (특히 2 부 참조 ).


이 링크에 감사드립니다. 내가 필요한 것과 정확히 똑같습니다. 특히 :diffget/:diffput시각적 모드에서는 재설정 / 커밋하려는 특정 줄을 선택할 수 있습니다. vim이 대단합니다.
goodniceweb

30

Atlassian의 SourceTree 를 사용하는 것이 좋습니다 . (무료) 이것은 사소한 일입니다. 개별 코드 덩어리 또는 개별 코드 줄을 빠르고 쉽게 스테이징 할 수 있습니다.

여기에 이미지 설명을 입력하십시오


1
SourceTree는 명령 줄을 통해 가능한 것보다 더 세밀하게 제어 할 수 있기 때문에이 목적에 적합한 도구라는 데 동의합니다.

18
@cupcake 나는 반대로 반대를 주장 할 것이다. SourceTree는 아마도 그 커맨드 라인 git 실행 파일을 사용한다는 것을 알았다. 본질적으로 항상 "command line"을 통해 동일한 (또는 그 이상) 세밀한 액션을 수행하는 것이 가능할 것이다.
tutuDajuju

2
세밀한 주장에 관계없이, 나는 덩어리와 개별 라인을 준비하는 것이 매우 쉬우므로 SourceTree 를 강력히 추천합니다 . i.imgur.com/85bNu4C.png
Mars Robertson

1
@tutuDajuju이 경우에는 사실이 확실하지 않습니다. SourceTree는 단계별로 어떤 부분을 단계별로 선택할 수 있습니다 . 전체 덩어리를 준비하지 않아도됩니다. 덩어리 중간에 2 줄을 배치 할 수 있습니다. 그러나 그것이 어떻게 달성되는지는 모른다. (현재, 나는 추적 할 수없는 파일에 대해 특정 줄을 스테이징 할 수없는 SourceTree의 문제를 해결하려고 노력 중입니다. 나는 해결책을 찾고 여기에 착륙했습니다 .git은 분명히 줄 단위 기능을 제공하지 않는 것 같습니다. 적어도 간단한 방법은 아닙니다.)
jpmc26

1
@Sun 50 행을 클릭하고 100 행을 Shift + 클릭 한 다음 준비하십시오. 당신은 쉽게 :) Sourcetree에 라인 50 ~ 100를 준비 할 수 있습니다
ryan123

26

사용에 협조 할 git add --patchA의 새 파일 처음으로 인덱스에 파일을 추가해야합니다 git add --intent-to-add:

git add -N file
git add -p file

23

변경 사항이 많고 변경 사항으로 커밋을 만들면 준비를 시작하기 전에 시작 지점을 임시로 저장하고 싶습니다.

이처럼 :

$ git stash -u
Saved working directory and index state WIP on master: 47a1413 ...
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 1st commit"
$ git checkout -p stash
... step through patch hunks
$ git commit -m "message for 2nd commit"
$ git stash pop

왜 마르 마의 대답은 때때로 많은 변화가 있고 상황을 준비하는 동안 실수를 저지르고 두 번째 단계로 넘어갈 수있는 헌신적 인 상태를 원한다는 것을 제외하고는 내가하는 일입니다.


12

emacs를 사용하는 경우, emacs를 위한 git 인터페이스를 제공하는 Magit을 살펴보십시오 . 그것은 지원 심술쟁이 준비 꽤 잘 (파일의 일부를).


Mx 쉘 창에서 편집기를 실행했을 때 편집기를 열려고하는 git 명령을 자주 사용합니다. magit은 그 광기를 차단하고 그것을위한 새로운 버퍼를 열었습니까? (어쨌든 배경-데마-데몬 힌트를주십시오. 어쨌든 고맙지 만 인생은 너무 짧습니다).
user2066657

아니요, 내가 알 수있는 한 이것을 가로 막지 않습니다. 그러나 (1) Emacs에서 쉘 창을 거의 사용하지 않으며 (2) 일반적으로 emacsclient를 사용하기 때문에 내 말을 받아들이지 마십시오. emacsclient 당신을위한 옵션이라면, 적어도 emacs를 가진 추가 창이 열리지 않고 "COMMIT_EDITMSG"버퍼가 기존 Emacs 창에서 열리지 않도록했습니다.
Mark van Lent


9

Git Extensions 를 사용하는 사람들을 위해 :

커밋 창에서 부분 커밋하려는 파일을 선택한 다음 오른쪽 창에서 커밋하려는 텍스트를 선택한 다음 선택을 마우스 오른쪽 단추로 클릭하고 상황에 맞는 메뉴에서 '선택한 줄 표시'를 선택하십시오.


2
'Stage selected line'에 대한 Git Extensions의 키보드 단축키 s는 커밋을 위해 파일의 일부를 빠르게 스테이징하는 데 매우 유용합니다.
Alchemistmatt

8

jdsumsion의 답변과 마찬가지로 현재 작업을 숨길 수 있지만 meld와 같은 difftool을 사용하여 숨김에서 선택한 변경 사항을 가져옵니다. 그렇게하면 수동으로 덩어리를 매우 쉽게 편집 할 수도 있습니다 git add -p.

$ git stash -u
$ git difftool -d -t meld stash
$ git commit -a -m "some message"
$ git stash pop

stash 메소드를 사용하면 코드가 여전히 작동하는지 커밋하기 전에 테스트 할 수 있습니다.


이것은 잘 작동하지만을 사용 git commit --amend하면 나중에 숨김을 표시 할 수 없거나 그렇게하는 방법이 있습니까?
Mark

7

이전 답변에 추가하고, 명령 행을 선호하는 경우, 입력 git add -e myfile하면 커밋하려는 행을 한 줄씩 선택할 수 있습니다.이 명령은 다음과 같이 차이점이있는 편집기를 엽니 다.

여기에 이미지 설명을 입력하십시오

알려진 줄은 추가로 알 수 있듯이 시작하는 +-은 삭제입니다. 그래서:

  • 추가를 준비하지 않으려면 해당 줄을 삭제하십시오.
  • 삭제를 준비하지 않으려면 -공백으로 바꾸십시오 .

git add -h방법으로 파일을 추가하는 방법 (파일 패치)에 대해 설명합니다.

추가 된 컨텐츠 추가 된 컨텐츠는 "+"로 시작하는 줄로 표시됩니다. 추가 라인을 삭제하여 스테이징을 방지 할 수 있습니다.

제거 된 컨텐츠 : 제거 된 컨텐츠는 "-"로 시작하는 행으로 표시됩니다. "-"를 ""(공백)으로 변환하여 제거가 준비되지 않도록 할 수 있습니다.

수정 된 내용 : 수정 된 내용은 "-"줄 (이전 내용 제거)과 "+"줄 (대체 내용 추가)로 표시됩니다. "-"행을 ""로 변환하고 "+"행을 제거하면 수정 사항이 스테이징되지 않도록 할 수 있습니다. 쌍의 절반 만 수정하면 색인이 혼동 될 수 있습니다.

주의 : 파일 내용을 변경하지 마십시오. 이렇게하는 것은 좋지 않습니다. 삭제되거나 추가 된 라인의 연산자를 변경하십시오.


어떤 이전 답변? 답변은 보유한 포인트 수에 따라 저장됩니다. 따라서 귀하의 답변은 다른 답변과 비교하여 작성했을 때와 다른 위치에 있습니다.
KulaGGin

참조 된 답변은 @theFreedomBanana
K의 것입니다. Symbol

6

vim-gitgutter 플러그인은 vim 편집기를 사용하지 않고 덩어리를 스테이징 할 수 있습니다.

:GitGutterStageHunk

이 외에도 일부 최신 IDE에서와 같이 diff sign column과 같은 다른 멋진 기능을 제공합니다.

덩어리의 일부만 vim-fugitive 스테이지해야하는 경우

:Gdiff

그런 다음 시각적 범위를 선택 :'<,'>diffput하거나 :'<,'>diffget개별 라인 변경을 스테이징 / 복귀 할 수 있습니다.



4

TortoiseGit으로 :

파일을 마우스 오른쪽 버튼으로 클릭하고을 사용하십시오 Context Menu → Restore after commit. 파일의 사본을 그대로 만듭니다. 그런 다음 TortoiseGitMerge에서 파일을 편집하고 커밋하지 않으려는 모든 변경 사항을 취소 할 수 있습니다. 해당 변경 사항을 저장 한 후 파일을 커미트 할 수 있습니다.


4

이 질문을받은 지 10 년이 지났습니다. 이 답변이 누군가에게 도움이 되길 바랍니다. GUI가 옵션이 아닌 여기 의 답변 에서 언급했듯이 Andrew Shadura의 crecord 확장 은 커밋 할 줄을 선택할 수있는 ncurses 창을 가져옵니다.

다음과 같이 확장을 설정하십시오.

git clone https://github.com/andrewshadura/git-crecord
cd git-crecord
./setup.py install
ln -s $PWD/git-crecord ~/.local/bin/git-crecord

git repo에 cd하고 다음과 같이 호출하십시오.

git crecord

그러면 아래와 같이 사용할 수있는 ncurses 인터페이스가 나타납니다. ncurses 창에서 다음 키를 누르면 특정 작업이 수행됩니다.

f       hunk toggle fold (arrow keys can also be used)
space   toggle hunk selection
a       toggle commit or amend
c       confirm and open commit window

샘플 사용법을 보여주는 스크린 캐스트예




2

git-meld-index- 웹 사이트에서 인용 :

git-meld-index는 meld 또는 다른 git difftool (kdiff3, spread 등)을 실행하여 git 인덱스 (git staging area라고도 함)의 변경 사항을 대화식으로 스테이징 할 수 있습니다.

이것은 git add -p 및 git add --interactive의 기능과 유사합니다. 어떤 경우에는 git add -p보다 meld를 사용하는 것이 더 쉽고 빠릅니다. 예를 들어 meld를 사용하면 다음을 수행 할 수 있기 때문입니다.

  • 더 많은 맥락을보십시오
  • 인라인 라인 차이를 참조하십시오
  • 직접 편집하고 '실시간'diff 업데이트 (키를 누를 때마다 업데이트 됨)를 참조하십시오.
  • 건너 뛰려는 모든 변경 사항에 대해 'n'이라고 말하지 않고 변경 사항으로 이동

용법

자식 저장소에서 다음을 실행하십시오.

git meld-index

다음과 같이 meld (또는 구성된 git difftool) 팝업이 표시됩니다.

LEFT : 작업 트리에서 복사 한 파일을 포함하는 임시 디렉토리

RIGHT : 인덱스 내용이있는 임시 디렉토리입니다. 여기에는 아직 색인에 없지만 작업 복사본에서 수정되거나 추적되지 않은 파일도 포함됩니다.이 경우 HEAD에서 파일 내용을 볼 수 있습니다.

행복해질 때까지 색인 (오른쪽)을 편집하십시오. 필요할 때 저장하십시오.

완료되면 meld를 닫으면 git-meld-index는 방금 편집 한 meld의 오른쪽에있는 임시 디렉토리의 내용과 일치하도록 색인을 업데이트합니다.


2

그것이 Windows플랫폼 에 있다면 내 의견으로 git gui는 파일 에서 몇 줄 에 stage/ 아주 좋은 도구입니다commitunstaged

1. 늠름한 현명한 :

  • unstagged Changes섹션 에서 파일을 선택 하십시오
  • 준비해야 할 코드 덩어리를 마우스 오른쪽 버튼으로 클릭
  • 고르다 Stage Hunk for commit

2. 현명한 선 :

  • unstagged Changes섹션 에서 파일을 선택 하십시오
  • 스테이징 할 라인을 선택하십시오
  • 마우스 오른쪽 버튼을 클릭하고 선택 Stage Lines for commit

3. 몇 줄을 제외한 전체 파일을 준비하려면 다음을 수행하십시오.

  • unstagged Changes섹션 에서 파일을 선택 하십시오
  • 프레스 Ctrl+T (Stage file to commit)
  • 선택한 파일이 이제 Staged Changes섹션으로 이동
  • 준비 할 라인을 선택하십시오
  • 마우스 오른쪽 버튼을 클릭하고 선택 UnStage Lines for commit

1

위의 답변 중 하나 에서 알 수 있듯이 git add --patch filename.txt

또는 짧은 형식 git add -p filename.txt

...하지만 이미 저장소에있는 파일의 경우 commit 명령에서 직접 --patch 플래그를 사용하는 것이 훨씬 좋습니다 (최근 충분한 버전의 git을 사용하는 경우). git commit --patch filename.txt

... 또는 짧은 형식 git commit -p filename.txt

... 그리고 커밋에 포함될 줄을 선택하기 위해 언급 된 키 (y / n 등)를 사용합니다.


git add -p filename.txt오류가 적은 공간 외에 " " 를 통해 무엇을 얻을 수 있습니까? 부분 파일 변경 사항을 엉망으로 만들면 커밋을 실행 취소하는 것보다 추가를 실행 취소하는 것이 좋습니다.
CTMacUser

왜 그런지 모르겠지만 'n'이라고 말하면 라인이 포함됩니다 .... 그리고 두 번째 덩어리에 'y'라고 말하면 포함됩니다.
chovy

1

git-cola 는 훌륭한 GUI 이며이 기능도 내장되어 있습니다. 준비 할 줄을 선택하고을 누릅니다 S. 선택하지 않으면 전체 덩어리가 준비됩니다.

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