Pro git - 2.2
Updated:
Pro git - 수정하고 저장소에 저장하기
- 워킹 디렉토리의 모든 파일은 크게 두 가지로 나뉜다.
-
Tracked(관리대상) : 이미 스냅샷에 포함되어 있던 파일. Unmodified, modified, staged 상태 중 하나. 즉, Git이 알고 있는 파일
-
Untracked(비관리대상) : tracked 나머지 파일. 워킹 디렉토리에 있는 파일 중 스냅샷에도 staging area에 포함되지 않은 파일.
내 생각 : 그럼 untracked는 새로 만든 파일을 말하는 듯?
1. 파일의 상태 확인하기
- 파일 상태 확인하기 위해서 git status 명령을 사용한다.
- 아래는 clone한 후에 바로 이 명령을 실행하면 아래와 같이 보임
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
- 위의 내용은 tracked 파일은 하나도 수정되지 않았다는 의미
- untracked 파일은 아직 없어서 목록에 나타나지 않는다.
-
현재 작업 중인 브랜치를 알려주며 서버의 같은 브랜치로부터 진행된 작업이 없는 것을 나타낸다.
- README 파일을 만든 예제는 다음과 같다.
$ echo 'My Project' > README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
README
nothing added to commit but untracked files present (use "git add" to track)
-
README파일은 새로 만든 파일이기 때문에git status를 실행하면 ‘Untracked files’에 들어 있다.내생각이 역시나 맞았다.
2. 파일을 새로 추적하기
- git add 명령으로 파일을 새로 추적할 수 있다.
$ git add README
- git status 명령을 다시 실행하면 README 파일이 tracked 상태이면서 커밋에 추가될 staged 상태라는 것을 확인할 수 있다.
$ 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)
new file: README
- “Changes to be committed” 에 들어 있는 파일은 Staged 상태라는 것을 의미
- 커밋하면
git add를 실행한 시점의 파일이 커밋되어 저장소 히스토리에 남는다. git add명령은 파일 또는 디렉토리의 경로를 아규먼트로 받는다. 디렉토리면 아래에 있는 모든 파일들까지 재귀적으로 추가
3. Modified 상태의 파일을 Stage 하기
- tracked 상태인 파일을 수정하는 방법
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)
new file: 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
CONTRIBUTING.md파일은 “Changes not staged for commit” 에 있다.- 이것은 수정한 파일이 Tracked 상태이지만 아직 Staged 상태는 아니라는 것이다.
- Staged 상태로 만들려면
git add명령을 실행해야 한다. - Merge 할 때 충돌난 상태의 파일을 Resolve 상태로 만들때도 사용한다.
- add의 의미는 프로젝트에 파일을 추가한다기 보다는 다음 커밋에 추가한다라는 의미.
- git add 명령 후 git status 명령으로 결과를 확인해보자.
$ git add 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)
new file: README
modified: CONTRIBUTING.md
- 두 파일 모두 staged 상태이므로 다음 커밋에 포함.
- 이때 CONTRIBUTING.md 파일을 수정했다고 가정. 그후 다시 git status 명령어 실행
$ vim 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)
new file: README
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
- 그러면 위와 같이
CONTRIBUTING.md가 Staged 상태이면서 동시에 Unstaged 상태로 나옴. - 따라서 commit 전 마지막 최종 git add 하여 최신 버전을 staged 상태로 만들어야 함
4. 파일 상태를 짤막하게 확인하기
git status -s또는git status --short처럼 옵션을 주면 현재 변경한 상태를 짤막하게 보여준다.
$ git status -s
M README
MM Rakefile
A lib/git.rb
M lib/simplegit.rb
?? LICENSE.txt
- 아직 추적하지 않는 새 파일 앞에는
??표시가 붙는다. - Staged 상태로 추가한 파일 중 새로 생성한 파일 앞에는
A표시가, 수정한 파일 앞에는M표시가 붙는다. - 왼쪽에는 Staging Area에서의 상태를, 오른쪽에는 Working Tree에서의 상태를 표시한다.
README파일 같은 경우 내용을 변경했지만 아직 Staged 상태로 추가하지는 않았다.lib/simplegit.rb파일은 내용을 변경하고 Staged 상태로 추가까지 한 상태이다.Rakefile은 변경하고 Staged 상태로 추가한 후 또 내용을 변경해서 Staged 이면서 Unstaged 상태인 파일이다.
5. 파일 무시하기
- 로그, 빌드 시스템이 자동으로 생성한 파일같이 무시하려면 .gitignore 파일을 만들고 그 안에 무시할 파일 패턴을 적는다.
$ cat .gitignore
*.[oa]
*~
- 첫 라인은 확장자가 “.o” or “.a” 인 파일을 Git이 무시하라는 의미
- 둘째 라인은 ~로 끝나는 모든 파일을 무시하라는 의미
5.1 .gitignore 패턴 규칙
- 아무것도 없는 라인이나,
#로 시작하는 라인은 무시한다. - 표준 Glob 패턴을 사용한다. 이는 프로젝트 전체에 적용된다.
- 슬래시(
/)로 시작하면 하위 디렉토리에 적용되지(Recursivity) 않는다. - 디렉토리는 슬래시(
/)를 끝에 사용하는 것으로 표현한다. - 느낌표(
!)로 시작하는 패턴의 파일은 무시하지 않는다.
- glob 패턴은 정규표현식을 단순하게 만든 것
- 애스터리스크(*)는 문자가 하나도 없거나 하나 이상을 의미. 전체를 의미하는듯?
- [abc] 는 중괄호 안에 있는 문자 중 하나를 의미. 즉, a,b,c중 하나
- 물음표(?)는 문자 하나를 의미
- [0-9] 처럼 중괄호 안의 캐릭터 사이에 하이픈(-)을 사용하면 그 캐릭터 사이에 있는 문자 하나를 말한다.
- 애스터리스크 2개를 사용하여 디렉터리 안의 디렉토리까지 지정할 수 있다.
-
즉,
a/**/z패턴은a/z,a/b/z,a/b/c/z디렉토리에 사용할 수 있다. - 아래는 예제
# 확장자가 .a인 파일 무시
*.a
# 윗 라인에서 확장자가 .a인 파일은 무시하게 했지만 lib.a는 무시하지 않음
!lib.a
# 현재 디렉토리에 있는 TODO파일은 무시하고 subdir/TODO처럼 하위디렉토리에 있는 파일은 무시하지 않음
/TODO
# build/ 디렉토리에 있는 모든 파일은 무시
build/
# doc/notes.txt 파일은 무시하고 doc/server/arch.txt 파일은 무시하지 않음
doc/*.txt
# doc 디렉토리 아래의 모든 .pdf 파일을 무시
doc/**/*.pdf
.gitignore파일을 하나만 두는 것이 아니라 하위 디렉토리에도 추가로 둘 수도 있다..gitignore정책은 현재.gitignore파일이 위치한 디렉토리와 그 하위 디렉토리에 적용된다.- 그래서 보통 루트 디렉토리에 둔다.
- 리눅스 커널 소스 저장소에는
.gitignore파일이 206개나 있음.
6. Staged와 Unstaged 상태의 변경 내용을 보기
- 파일이 변경됐다는 사실이 아니라 어떤 내용이 변경되었는지 살펴 보려면 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옵션을 사용한다. (–cached 사용해도 똑같다) - 이 명령은 저장소에 커밋한 것과 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 @@
+My Project
- git diff 명령은 마지막으로 커밋한 후에 수정한 것들 전부를 보여주지 않는다. git diff는 Unstaged 상태인 것들만 보여준다.
- 수정한 파일을 모두 Staging Area에 넣었다면
git diff명령은 아무것도 출력하지 않는다. - 수정한 파일을 모두 Staging Area에 넣고 다시 파일을 수정한 후 git diff 명령을 사용한다면 Staged 상태인 것과 Unstaged 상태인 것을 비교한다.
6.1 외부 도구로 비교하기
git diff대신git difftool명령을 사용해서 emerge, vimdiff 같은 도구로 비교할 수 있다.git difftool --tool-help라는 명령은 사용가능한 도구를 보여준다.
7. 변경사항 커밋하기
- git commit
# 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
- On branch master #을 지우고 wq로 저장하면 커밋됨
- -v 옵션을 추가하면 편집기에 diff 메시지도 추가
- -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
8. Staging Area 생략하기
git commit명령을 실행할 때-a옵션을 추가하면 Git은 Tracked 상태의 파일을 자동으로 Staging Area에 넣는다
$ 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(-)
9. 파일 삭제하기
-
git rm명령으로 Tracked 상태의 파일을 삭제한 후에(정확하게는 Staging Area에서 삭제하는 것) 커밋해야 한다. - 이 명령은 워킹 디렉토리에 있는 파일도 삭제하기 때문에 실제로 파일도 지워진다.
- 단순히 워킹 디렉터리에서 파일을 삭제하고
git status명령으로 상태를 확인하면 Git은 현재 “Changes not staged for commit” (즉, Unstaged 상태)라고 표시해준다.
$ rm PROJECTS.md
$ 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: PROJECTS.md
no changes added to commit (use "git add" and/or "git commit -a")
git rm명령을 실행하면 삭제한 파일은 Staged 상태가 된다.
$ git rm PROJECTS.md
rm 'PROJECTS.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)
deleted: PROJECTS.md
- 커밋하면 파일은 삭제되고 Git은 이 파일을 더는 추적하지 않는다
- 이미 파일을 수정했거나 Staging Area에(역주 - Git Index라고도 부른다) 추가했다면
-f옵션을 주어 강제로 삭제해야 한다. - 반대로 Staging Area에서만 제거하고 워킹 디렉토리에 있는 파일은 지우지 않고 남겨둘 수 있다.
- .gitIgnore 파일에 추가하는 것을 빼먹었거나 대용량 로그 파일, 컴파일된 파일 같은 것을 실수로 추가했을 때 쓴다. –cached 옵션을 사용한다.
$ git rm --cached README
- 여러 개의 파일이나 디렉토리를 한꺼번에 삭제할 수도 있다. 아래와 같이
git rm명령에 file-glob 패턴을 사용한다.
$ git rm log/\*.log
*앞에\을 사용한 것을 기억하자. 파일명 확장 기능은 쉘에만 있는 것이 아니라 Git 자체에도 있기 때문에 필요하다.- 이 명령은
log/디렉토리에 있는.log파일을 모두 삭제한다
$ git rm \*~
- 이 명령은
~로 끝나는 파일을 모두 삭제한다.
10. 파일 이름 변경하기
- 파일 이름의 변경이나 파일의 이동을 명시적으로 관리하지 않는다.
- 다시 말해서 파일 이름이 변경됐다는 별도의 정보를 저장하지 않는다.
- 아래와 같이 이름을 변경할 수 있다.
$ 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
- 하지만 변경 된 사실은 알고 있다. 그리고 아래는 위의 명령을 수행한 것과 같은 명령어다.
$ mv README.md README
$ git rm README.md
$ git add README
- git mv 명령은 일종에 단축 명령어다.
- 중요한 것은 mv만 썼을 때 꼭 rm / add를 실행줘야 한다.