Git 다 써보기, (2) Git 기초
우리가 git init을 한다는게 어떤것인지 부터 file 을 추적하고 추적을 그만두는 방법까지 기초적인 문법을 이해하고 사용해 본다.
0. Git 저장소 만들기
Git 저장소를 쓰는 방법
- 아직 버전관리를 하지 않은 로컬 디렉토리를 선택해서 Git 저장소를 생성
- 다른 어딘가에서 Git 저장소를 Clone 하는 방법
기존 디렉토리를 Git 저장소로 만들기
버전 관리를 하지 않은 기존 프로젝트를 Git으로 관리하고 싶은 경우 일단 프로젝트의 디렉토리로 이동한다.
cd /C:\Users\ashgh\workspace\git_test
그리고 아래 명령어를 실행한다.
$ git init
이 명령어는 .git 이라는 __하위 디렉토리__를 만드는 명령어이다. .git 디렉토리에는 저장소에 필요한 뼈대 파일들이 들어있다.
이 명령만으로는 아직 프로젝트의 어떤 파일도 관리가 되지 않는다.
Git이 파일을 관리 하게 하기 위해선 저장소에 파일을 추가하고 __커밋__을 해야한다.
git add 명령으로 파일을 추가하고 git commit 명령으로 커밋한다.
$ git add *.txt
$ git add LICENSE
$ git commit -m 'initial project version'
기존 저장소 Clone 해오기
다른 프로젝트를 참여(Contribute) 하거나 Git 저장소를 복사하고 싶을떈 git clone 을 한다.
git clone 을 사용하면 프로젝트 히스토리를 모두 받아온다. 실제로 서버의 디스크가 망가져도 클라이언트 저장소 중에서 아무거나 하나 가져다 복구를 진행하면 된다. (서버에만 적용한 설정은 복구가 불가하지만 데이터는 복구 하면 된다.)
git 을 clone 하는 방법은 ssh/https 방법 이 있다. 그건 편한데로
Git은 다양한 프로토콜을 지원한다. https:// 외 git:// 를 사용할수도 있고.
user@server:path/to/repo.git 처럼 SSH 프로토콜을 사용할수도 있다.
1. 수정하고 저장소에 저장하기
Git 저장소를 만들고 working directory 에 Checkout을 해 보았다. 이제는 파일을 수정하고 파일의 스냅샷을 커밋해 보자 파일을 수정하다 저장하고 싶다면 스냅샷을 커밋하면 된다.
워킹 디렉토리 :
체크아웃 :
파일 스냅샷 :
워킹 디렉토리의 모든 파일은 Tracked(관리대상) 과 Untracked(비관리대상) 으로 나뉜다. Tracked 파일은 이미 스냅샷에 포함되어 있는 파일이다. Tracked 파일은 또 Unmodified (수정하지 않음) 과 Modified (수정함) 그리고 Staged 상태중 하나이다. 즉 Git이 알고있는 파일이라는 것이다.
이외의 모든 파일은 모두 Untracked 파일이다. Untracked 파일은 워킹 디렉토리에 있는 파일 중 스냅샷에도 Staging Area 에도 포함되지 않은 파일이다. 처음 저장소를 Clone 한다면 모든 파일은 Tracked 이면서 Unmodified 상태이다. 파일을 Checkout 하고 아무런 수정이 없기 때문
그러면 저장소에서 어떠한 파일을 수정하면 Git은 그 파일을 Modified 상태로 인식하게 된다. 실제로 커밋을 위해선 수정 파일을 Staged 상태로 만들고, Staged 상태 파일을 커밋해야한다. 이러한 라이프 사이클을 계속 반복한다.
Staging Area :
파일의 상태 확인하기
파일의 상태를 확인하려면 보통 git status 명령을 사용하여 확인한다.
이전 위에서 commit을 한 생태에서 git status 를 하였을땐 아래와 같은 결과가 나온다.
C:\Users\ashgh\workspace\git-test>git status
On branch master
nothing to commit, working tree clean
Tracked 파일이 하나도 수정되지 않았다는 의미이다. 또한 현재는 Untracked 파일이 하나도 존재하지 않아 목록에서 보이지가 않는다.
Untracked 파일을 하나 만들어 보도록 하자.
README 파일을 하나 만들어 볼 생각이다.
난 윈도우서 포스팅 중이라,, notepad 명령어를 사용하였고, vi nano등 편한 편집기를 사용하면 될것 같다.
$ notepad README.md
$ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
nothing added to commit but untracked files present (use "git add" to track)
Untracked file 이 들어있는것을 볼 수 있다.
Git은 Untracked 파일을 아직 스냅샷(커밋)에 넣지 않은 파일이라고 보고, Tracked 상태가 되기 전까지는 Git 은 절대 그 파일을 커밋하지 않는다. 그래서 일하면서 생성하는 바이너리 파일 같은 것을 커밋하는 실수를 하지 않게 된다.
파일의 추적
위에서 git add 명령어를 통해 파일을 Tracked 추적 상태로 전환할수 있다고 하였다. 명령어를 실행해 보자.
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
Changes to be committed’’ 에 들어 있는 파일은 Staged 상태라는 것을 의미한다. 이것을 커밋하면 git add를 실행한 시점의 파일이 커밋되어 저장소 히스토리에 남게된다. 앞에서 git init 명령을 실행한 후 git add (files) 명령을 실행했던 걸 기억할 것이다. 이 명령을 통해 디렉토리에 있는 파일을 추적하고 관리하도록 한다. git add 명령은 파일 또는 디렉토리의 경로를 아규먼트로 받는다. 디렉토리면 아래에 있는 모든 파일들 까지 재귀적으로 추가한다.
Modified 상태 파일을 Stage 하기
이미 traced 상태인 파일을 수정하면 어떻게 될까?
이전에 Tracked 한 test.txt 파일을 수정해 보자.
$ notepad test.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.txt
test.txt 파일은 `Changes not staged for commit’ 라는 메세지와 함께 뜬다. 이것은 수정한 파일이 Tracked 상태이지만 아직 Staged 상태는 아니라는 것이다. Staged 상태로 만드려면 git add 명령을 실행해야 한다. git add 명령은 파일을 새로 추적할 때도 사용하고 수정한 파일을 staged 상태로 만들 때도 사용한다. Merge 할 때 충돌난 상태의 파일을 Resolve 상태로 만들때도 사용한다.
git add 명령어를 실행하여 test.txt, readme.md 파일을 모두 staged상태로 만들고 git status 명령으로 결과를 확인한다.
$ git add.
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: test.txt
두 파일 모두 Stage 상태 이므로 다음 커밋에 포함된다. 이상태에서 추가로 수정할게 있다면 어떻게 하면될까? test.txt 파일을 다시 수정한다고 Git이 커밋할 준비가 되었다고 알까? 그렇지 않다 . git status 명령어를 통해 파일 상태를 다시 확인해 보자.
$git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: test.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.txt
test.txt 가 staged 상태이면서 동시에 unstaged 상태로 나온다…. git add 명령어를 실행하면 git은 파일을 바로 stage 상태로 만든다. 지금 이시점에서 커밋을 하면 git commit 명령을 실행하는 시점의 버전이 커밋이 되는것이 아닌 마지막 git add 명령을 실행했을 때 버전이 커밋된다. 그러니 git add 명령을 실행한 후 또 파일을 수정하면 git add 명령을 다시 실행해서 최신 버전을 stage 상태로 만들어야 한다.
$git add test.txt
$git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: test.txt
파일 상태 간단히 확인하기. git status -s && git status -short
git status명령으로 확인하 수 있는 내용이 많이 있다. 이걸 좀 간단히 보기 위해선 git status -s 명령어 또는 git status –short 처럼 옵션을 통해 상태를 확인할 수 있다.
git status --short
A README.md
M test.txt
?? LICENSE.txt
- 아직 추적 하지 않은 새 파일 앞에는 ?? 표시가 붙는다.
- Staged 상태로 추가한 파일중 새로 생성한 파일 앞에는 A표시가,
- 수정한 파일 앞에는 M표시가 붙는다.
파일 무시하기
어떤 파일은 Git 이 관리할 필요가 없다. 보통 로그 파일이나 빌드 시스템이 자동으로 생성한 파일이 그러하다. 그런 파일을 무시하려면 .gitignore 파일을 만들고 그 안에 무시할 파일 패턴을 적으면 된다.
.gitignore
igno*
*.log
mnt/
첫라인은 igno라고 시작하는 모든 파일들을 무시한다는 뜻이고, 두번째 라인은 log들을 무시한다는 것이다.
.gitignore 파일을 보통 처음에 만들어 두는것이 좋다. 그래야 Git 저장소에 커밋하고 싶지 않은 파일을 실수로 커밋하는 일을 방지할 수 있다.
.gitignore 파일에 입력하는 패턴은 아래 규칙을 따른다.
- 아무것도 없는 라인이나, #로 시작하는 라인은 무시
- 표준 Glob 패턴을 사용.
- 슬래시(/)로 시작하면 하위 디렉토리에 적용되지 않는다.
- 디렉토리는 슬래시(/)를 끝에 사용하는 것으로 표현한다.
- 느낌표(!)로 시작하는 패턴의 파일은 무시하지 않는다.
* Glob 패턴
Glob 패턴은 정규표현식을 간단히 만든것이고 보통 쉘에서 많이 사용한다.
애스터리스크(*)는 문자가 하나도 없거나 하나 이상을 의미,
[abc] 는 중괄호 안에 있는 문자 중 하나를 의미,
?는 문자 하나를 말한다.
[0-9]는 중괄호 안 캐릭터 사이에 하이픈을 사용하면 그 캐릭터 사이에 있는 무자 하나를 말한다.
애스터리크 2개를 사용하여 디렉토리 안에 디렉토리 까지 지정할수 있다.
a/**/z 패턴은 a/z, a/b/z, a/b/c/z 디렉토리에 사용할 수 있다.
Glob 정규표현식은 이전에도 다루었고 다음에도 내 블로그서 다루어볼 예정이다.
.gitignore 파일의 예시
# 확장자가 log인 파일 무시
*.log
# 윗라인에서 확장자가 .a인 파일은 무시하게 했지만 necessary.log 는 무시 하지 않음
!necessary.log
# 현재 디렉토리에 있는 TODO, 파일은 무시하고 subdir/TODO 처럼 하위디렉토리에 있는 파일은 무시하지 않음
/TODO
# build/ 디렉토리에 있는 모든 파일을 무시
build/
# doc/notes.txt 파일은 무시하고 doc/server/arch.txt 파일은 무시하지 않음
doc/*.txt
# doc 디렉토리 아래의 모든 .txt 파일을 무시
doc/**/*.txt
Staged 의 Unstaged 상태의 변경내용을 확인하기 git diff
단순히 파일 변경 사실확인이 아닌 어떠한 내용이 변경됐는지 확인할 방법이 있을까?
git diff 명령어를 사용하면 된다.
Patch 처럼 어떤 라인을 추가했고ㅡ 삭제했는지가 궁금할때 사용하면 된다.
git diff 를 사용하면 수정 했지만 아직 staged 상태가 아닌 파일을 비교해 볼수 있다.
$git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: test.txt
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.txt
$git diff
C:\Users\ashgh\workspace\git-test>git diff
diff --git a/test.txt b/test.txt
index 6c02861..5204259 100644
--- a/test.txt
+++ b/test.txt
@@ -1,4 +1,6 @@
문서 수정
test 문서 수정전
-또 수정
\ No newline at end of file
+또 수정
+
+또또 수정
\ No newline at end of file
이 명령은 워킹 디렉토리에 있는 것과 Staging Area에 있는 것을 비교한다. 그래서 수정하고 아직 Stage 하지 않은 것을 보여준다
$git add .
$git diff
아무것도 안나온다.
$git diff --cached
$git diff --staged
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2741087
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+# Git 모두 다 해보기
+
+순서가 좀 튜토리얼 부터는 아니지만,,
+
+0. stash
+1. git 의 기초
diff --git a/test.txt b/test.txt
index 45c48e6..5204259 100644
Staged 상태인 파일은 git diff –cached옵션으로 확인이 가능하다.
변경사항 커밋하기
수정한 것을 커밋하기 위해 Staging Area에 파일을 정리했다. Unstaged 상태 파일은 커밋되지 않는다는 것을 기억해야 한다.
$git commit
Git 설정에 지정된 편집기가 실행되고, 아와 같은 텍스트가 자동으로 포함된다.
편집기는 쉘의 EDITOR 환경 변수에 등록된 편집기이고 보통은 VIM이나 Emacs를 사용한다.
git config –global core.editor를 통해 편집기를 확인할 수 있다.
우리가 이렇게 커밋을 하고 나면 commit 명령어는 몇가지 정보를 출력하는데
git commit
[master 664daa9] commit
2 files changed, 12 insertions(+), 1 deletion(-)
create mode 100644 README.md
위 예제에서는 master 브랜치에 커밋을 했고 체크섬은 664daa9 이다.
그리고 수정한 파일과 삭제, 추가된 라인이 몇라인인가 까지도 알려준다.
Git은 Staging Area에 속한 스냅샷을 커밋한다는 것을 기억하자.
커밋할때마다 프로젝트의 스냅샷을 기록하기 때문에 나중에 스냅샷끼리 비교하거나 예전 스냅샷으로 되돌릴 수 있다.
Staging Area 생략 하기
Staging Area 는 커밋할 파일을 정리한다는 점에서 매우 유용하지만 복잡하고 필요하지 않을때도 있다.
이럴때 아주 쉽게 Staging Area를 생략할수도 있다. git commit 명령을 실행할 때 -a 옵션을 추가하면 Git 은 Tracked 상태의 파일을 자동으로 Staging Area에 넣는다.
git add 를 줄일수 있는 좋은 방법이다.
파일 삭제하기
Git에서 파일을 제거하려면 git rm 명령으로 Tracked 상태 파일을 삭제한 후에 (Staging Area)에서 커밋을 해야 한다. 이 명령은 워킹 디렉토리에 있는 파일도 삭제하기 때문에 실제 파일도 지워지게 된다.
Git 명령을 사용하지 않고 단순히 워킹 디렉터리에서 파일을 삭제하고 git status 명령으로 상태를 확인하면 Git은 `Changes not staged for commit’’ (즉, Unstaged 상태)라고 표시 한다.
remove.txt 파일을 추가하고 파일 자체를 명령어를 통해 삭제 하였다.
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: remove.txt
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: remove.txt
위와 같은 상태에서
git rm 명령어를 사용해보자
$git rm remove.txt
rm 'remove.txt'
$git status
On branch master
nothing to commit, working tree clean
이상태에서 커밋을 하면 파일은 삭제 되고 Git은 이 파일을 더이상 추적하지 않게 된다. 이미 파일을 수정했거나 Staging Area에 추가했다면 -f 옵션을 주어 강제로 삭제해야할 필요가 생긴다.
또 Staging Area 에서만 제거하고 워킹 디렉토리에 있는 파일은 지우지 않고 남겨둘수도 있따. .gitignore 파일에 추가하는것을 빼먹거나 대용량 로그파일이나 컴파일된 파일인.a 파일같은 것을 추가했을때 쓴다 .
–cached옵션을 사용해여 명령을 실행한다.
$git rm --cached REAME
$git rm –cached README.md rm ‘README.md’
$ git status
On branch master
Changes to be committed:
(use “git restore –staged
Untracked files:
(use “git add
3. 커밋 히스토리 조회
저장소의 히스토리를 보고 싶을때 Git 에는 히스토리를 조회하는 명령어인 git log 가 있다.
원하는 히스토리를 검색할 수도 있도록 git log 는 매우 다양한 옵션을 지원한다 .
여러 옵션 중 -p –patch 는 각 커밋의 diff 결과를 보여준다 .
-2 옵션은 가장 최근 2개의 결과만 보여준다.
4. 되돌리기
작업을 하다 모든 단계에서 어떤 것은 되돌리고 싶을때가 있다. Git을 사용함여 실수는 대부분 되돌리수 있지만 되돌린것은 복구를 할수는 없다.
완료한 커밋을 수정하려면 수정하려면 어떻게 해야할까? 너무 일찍 커밋하거나 파일을 빼먹었을 때, 메세지를 잘못적었을때 다시 커밋을 하고 싶다면 파일 작업을 하고 Staging Area에 추가한다음 –amend 옵션을 통해 커밋을 재작성하는 것이 가능하다.
이 명령은 Staging Area를 사용하여 커밋한다.
만약 마지막으로 커밋하고 나서 수정한 것이 없다면, 조금 전에 커밋한 모든 것이 같다. 이때는 커밋 메세지만 수정한것과 같다.
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
이 실행명령어는 3개 모두 커밋한개로 기록된다. 두번째 커밋이 첫 커밋을 덮어쓴다.
파일 상태를 Unstage로 변경
다음은 Staging Area와 워킹 디렉토리를 넘나드는 방법이다 .
두 영역의 상태를 확인할 때마다 변경된 상태를 되돌리는 방법을 알려주기 때문에 매우 편리하다.
두개의 파일을 변경하고 git add . 을 하였다.
두개의 파일 모두 staging area에 들어가게 된다. 이제 둘중하나를 꺼내고 싶다면 어떻게 꺼낼수 있을까?
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: test.txt
아래 보면 Changed to be commited 밑 git reset Head
$ git reset HEAD test.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: test.txt
Modified 파일 되돌리기
최근 커밋된 버전으로 돌릴수 있는 방법이 있을까? (아니면 처음 Clone 했을 때처럼 워킹 디렉토리에 처음 Checkout 한 그 내용으로)
git status 명령어를 다시 확인해 보자. 이게 위험한 명령어라 그런지 지금은 status에서 안나오는것 가다.
원래 파일로 덮어쓴다는 명령어이기 때문에 수정한 내용이 그냥 덮어써져 버린다. 수정한 내용이 진짜 마음에 들지 않을때만 사용해야 하는 위험한 명령어이다.
$ git checkout -- README.md
만약 변경한 내용을 쉽게 버릴수 없고 코드를 돌려야 한다면 Stash나 Branch를 이용해야 한다.
Branch
Git으로 커밋 한 모든 것은 언제나 복구할 수 있다. 삭제한 브랜치에 있었던 것도, --amend 옵션으로 다시 커밋한 것도 복구할 수 있다(자세한 것은 데이터 복구 에서 다룬다). 하지만 커밋하지 않고 잃어버린 것은 절대로 되돌릴 수 없다.