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를 실행줘야 한다.