모든 내용은 https://git-scm.com/book를 참고하여 만들었습니다.
수정하고 저장소에 저장하기
Staged와 Unstaged 상태의 변경 내용을 보기
단순히 파일이 변경됐다는 사실이 아니라 어떤 내용이 변경됐는지 살펴보려면 git status
명령이 아니라 git diff
명령을 사용해야 한다. 보통 우리는 ‘수정했지만, 아직 Staged
파일이 아닌 것?’과 ‘어떤 파일이 Staged 상태인지?’가 궁금하기 때문에 git status
명령으로도 충분하다. 더 자세하게 볼 때는 git diff
명령을 사용하는데 Patch
처럼 어떤 라인을 추가했고 삭제했는지가 궁금할 때 사용한다. git diff
는 나중에 더 자세히 다룬다.
README 파일을 수정해서 Staged
상태로 만들고 CONTRIBUTING.md 파일은 그냥 수정만 해둔다. 이 상태에서 git status
명령을 실행하면 아래와 같은 메시지를 볼 수 있다.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: README
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: CONTRIBUTING.md
git diff
명령을 실행하면 수정했지만 아직 staged
상태가 아닌 파일을 비교해 볼 수 있다.
$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
Please include a nice description of your changes when you submit your PR;
if we have to read the whole diff to figure out why you're contributing
in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.
If you are starting to work on a particular area, feel free to submit a PR
that highlights your work in progress (and note in the PR title that it's
이 명령은 워킹 디렉토리에 있는 것과 Staging Area
에 있는 것을 비교한다. 그래서 수정하고 아직 Stage
하지 않은 것을 보여준다.
만약 커밋하려고 Staging Area
에 넣은 파일의 변경 부분을 보고 싶으면 git diff --staged
옵션을 사용한다. 이 명령은 저장소에 커밋한 것과 Staging Area
에 있는 것을 비교한다.
$ git diff --staged
diff --git a/README b/README
new file mode 100644
index 0000000..03902a1
--- /dev/null
+++ b/README
@@ -0,0 +1,4 @@
+My Project
꼭 잊지 말아야 할 것이 있는데 git diff
명령은 마지막으로 커밋한 후에 수정한 것들 전부를 보여주지 않는다. git diff
는 Unstaged
상태인 것들만 보여준다. 이 부분이 조금 헷갈릴 수 있다. 수정한 파일을 모두 Staging Area
에 넣었다면 git diff
명령은 아무것도 출력하지 않는다.
CONTRIBUTING.md 파일을 Stage
한 후에 다시 수정해도 git diff
명령을 사용할 수 있다. 이때는 Staged
상태인 것과 Unstaged
상태인 것을 비교한다.
$ git add CONTRIBUTING.md
$ echo '# test line' >> CONTRIBUTING.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: CONTRIBUTING.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: CONTRIBUTING.md
git diff
명령으로 Unstaged
상태인 변경 부분을 확인할 수 있다.
$ git diff
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 643e24f..87f08c8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -119,3 +119,4 @@ at the
## Starter Projects
See our [projects list](https://github.com/libgit2/libgit2/blob/development/PROJECTS.md).
+# test line
Staged 상태인 파일은 git diff --cached
옵션으로 확인한다. --staged
와 --cached
는 같은 옵션이다.
$ git diff --cached
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8ebb991..643e24f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -65,7 +65,8 @@ branch directly, things can get messy.
Please include a nice description of your changes when you submit your PR;
if we have to read the whole diff to figure out why you're contributing
in the first place, you're less likely to get feedback and have your change
-merged in.
+merged in. Also, split your changes into comprehensive chunks if your patch is
+longer than a dozen lines.
If you are starting to work on a particular area, feel free to submit a PR
that highlights your work in progress (and note in the PR title that it's
Note
외부 도구로 비교하기
git diff
명령은 여기저기서 써 먹는다. 즐겨 쓰거나 결과를 아름답게 보여주는 Diff 도구가 있으면 사용할 수 있다. git diff
대신 git difftool
명령을 사용해서 emerge
, vimdiff
같은 도구로 비교할 수 있다. 상용 제품도 사용할 수 있다. git difftool --tool-help
라는 명령은 사용가능한 도구를 보여준다.
변경사항 커밋하기
수정한 것을 커밋하기 위해 Staging Area
에 파일을 정리했다. Unstaged
상태의 파일은 커밋되지 않는다는 것을 기억해야 한다. Git은 생성하거나 수정하고 나서 git add
명령으로 추가하지 않은 파일은 커밋하지 않는다. 그 파일은 여전히 Modified
상태로 남아 있다. 커밋하기 전에 git status
명령으로 모든 것이 Staged
상태인지 확인할 수 있다. 그 후에 git commit
을 실행하여 커밋한다.
$ git commit
Git 설정에 지정된 편집기가 실행되고, 아래와 같은 텍스트가 자동으로 포함된다 (아래 예제는 Vim 편집기의 화면이다. 이 편집기는 쉘의 $EDITOR 환경 변수에 등록된 편집기이고 보통은 Vim이나 Emacs을 사용한다. 또 시작하기 에서 설명했듯이 git config --global core.editor
명령으로 어떤 편집기를 사용할지 설정할 수 있다).
편집기는 아래와 같은 내용을 표시한다(아래 예제는 Vim 편집기).
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Your branch is up-to-date with 'origin/master'.
# Changes to be committed:
# new file: README
# modified: CONTRIBUTING.md
#
~
~
~
".git/COMMIT_EDITMSG" 9L, 283C
자동으로 생성되는 커밋 메시지의 첫 라인은 비어 있고 둘째 라인부터 git status
명령의 결과가 채워진다. 커밋한 내용을 쉽게 기억할 수 있도록 이 메시지를 포함할 수도 있고 메시지를 전부 지우고 새로 작성할 수 있다 (정확히 뭘 수정했는지도 보여줄 수 있는데, git commit
에 -v
옵션을 추가하면 편집기에 diff
메시지도 추가된다). 내용을 저장하고 편집기를 종료하면 Git은 입력된 내용(#로 시작하는 내용을 제외한)으로 새 커밋을 하나 완성한다.
메시지를 인라인으로 첨부할 수도 있다. commit
명령을 실행할 때 아래와 같이 -m
옵션을 사용한다.
$ git commit -m "Story 182: Fix benchmarks for speed"
[master 463dc4f] Story 182: Fix benchmarks for speed
2 files changed, 2 insertions(+)
create mode 100644 README
이렇게 첫번째 커밋을 작성해보았다. commit 명령은 몇 가지 정보를 출력하는데 위 예제는 (master) 브랜치에 커밋했고 체크섬은 (463dc4f)이라고 알려준다. 그리고 수정한 파일이 몇 개이고 삭제됐거나 추가된 라인이 몇 라인인지 알려준다.
Git은 Staging Area
에 속한 스냅샷을 커밋한다는 것을 기억해야 한다. 수정은 했지만, 아직 Staging Area
에 넣지 않은 것은 다음에 커밋할 수 있다. 커밋할 때마다 프로젝트의 스냅샷을 기록하기 때문에 나중에 스냅샷끼리 비교하거나 예전 스냅샷으로 되돌릴 수 있다.
Staging Area 생략하기
Staging Area
는 커밋할 파일을 정리한다는 점에서 매우 유용하지만 복잡하기만 하고 필요하지 않은 때도 있다.
아주 쉽게 Staging Area를 생략할 수 있다.
git commit
명령을 실행할 때 -a
옵션을 추가하면 Git은 Tracked
상태의 파일을 자동으로 Staging Area
에 넣는다. 그래서 git add
명령을 실행하는 수고를 덜 수 있다.
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: CONTRIBUTING.md
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m 'added new benchmarks'
[master 83e38c7] added new benchmarks
1 file changed, 5 insertions(+), 0 deletions(-)
이 예제에서는 커밋하기 전에 git add
명령으로 CONTRIBUTING.md 파일을 추가하지 않았다는 점을 눈여겨보자. -a
옵션을 사용하면 모든 파일이 자동으로 추가된다. 편리한 옵션이긴 하지만 주의 깊게 사용해야 한다. 생각 없이 이 옵션을 사용하다 보면 추가하지 말아야 할 변경사항도 추가될 수 있기 때문이다.
파일 삭제하기
Git에서 파일을 제거하려면 git rm
명령으로 Tracked
상태의 파일을 삭제한 후에( 정확하게는 Staging Area에서 삭제하는 것 ) 커밋해야 한다. 이 명령은 워킹 디렉토리에 있는 파일도 삭제하기 때문에 실제로 파일도 지워진다.
Git 명령을 사용하지 않고 단순히 워킹 디렉터리에서 파일을 삭제하고 git status 명령으로 상태를 확인하면 Git은 현재 “Changes not staged for commit”(즉, Unstaged 상태)라고 표시해준다.
$ rm grit.gemspec
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: grit.gemspec
no changes added to commit (use "git add" and/or "git commit -a")
그리고 git rm
명령을 실행하면 삭제한 파일은 Staged
상태가 된다.
$ git rm grit.gemspec
rm 'grit.gemspec'
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: grit.gemspec
커밋하면 파일은 삭제되고 Git은 이 파일을 더는 추적하지 않는다. 이미 파일을 수정했거나 Index에(역주 - Staging Area을 Git Index라고도 부른다) 추가했다면 -f
옵션을 주어 강제로 삭제해야 한다. 이 점은 실수로 데이터를 삭제하지 못하도록 하는 안전장치다. 커밋 하지 않고 수정한 데이터는 Git으로 복구할 수 없기 때문이다.
또 Staging Area
에서만 제거하고 워킹 디렉토리에 있는 파일은 지우지 않고 남겨둘 수 있다. 다시 말해서 하드디스크에 있는 파일은 그대로 두고 Git만 추적하지 않게 한다. 이것은 .gitignore
파일에 추가하는 것을 빼먹었거나 대용량 로그 파일이나 컴파일된 파일인 .a 파일 같은 것을 실수로 추가했을 때 쓴다. --cached
옵션을 사용하여 명령을 실행한다.
$ git rm --cached README
여러 개의 파일이나 디렉토리를 한꺼번에 삭제할 수도 있다. 아래와 같이 git rm 명령에 file-glob 패턴을 사용한다.
$ git rm log/\*.log
* 앞에 \ 을 사용한 것을 기억하자. 파일명 확장 기능은 쉘에만 있는 것이 아니라 Git 자체에도 있기 때문에 필요하다. 이 명령은 log/ 디렉토리에 있는 .log
파일을 모두 삭제한다. 아래의 예제처럼 할 수도 있다.
$ git rm \*~
이 명령은 ~ 로 끝나는 파일을 모두 삭제한다.
파일 이름 변경하기
Git은 다른 VCS 시스템과는 달리 파일 이름의 변경이나 파일의 이동을 명시적으로 관리하지 않는다. 다시 말해서 파일 이름이 변경됐다는 별도의 정보를 저장하지 않는다. Git은 똑똑해서 굳이 파일 이름이 변경되었다는 것을 추적하지 않아도 아는 방법이 있다. 파일의 이름이 변경된 것을 Git이 어떻게 알아내는지 살펴보자.
이렇게 말하고 Git에 mv 명령이 있는 게 좀 이상하겠지만, 아래와 같이 파일 이름을 변경할 수 있다.
$ git mv file_from file_to
잘 동작한다. 이 명령을 실행하고 Git의 상태를 확인해보면 Git은 이름이 바뀐 사실을 알고 있다.
$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
renamed: README.md -> README
사실 git mv 명령은 아래 명령어를 수행한 것과 완전 똑같다.
$ mv README.md README
$ git rm README.md
$ git add README
git mv
명령은 일종의 단축 명령어이다. 이 명령으로 파일 이름을 바꿔도 되고 mv
명령으로 파일 이름을 직접 바꿔도 된다. 단지 git mv
명령은 편리하게 명령을 세 번 실행해주는 것 뿐이다. 어떤 도구로 이름을 바꿔도 상관없다. 중요한 것은 이름을 변경하고 나서 꼭 rm/add
명령을 실행해야 한다는 것 뿐이다.