git은 소스 코드 관리를 위한 분산 버전 관리 시스템이다.
windows_git 해당 사이트 접속 시 자동으로 다운 받아지며 안 받아지면 수동으로 32bit(x86) 64bit(x64)에 맞춰서 다운로드해 주자
패키지 관리 도구를 이용하여 설치한다.
Fedora
$ sudo yum install git
Debian
$ sudo apt-get install git
Mac은 Mac 패키지 관리자인 homebrew
로 설치하는 게 업데이트나 관리 면에서 유용하다.
$ brew install git
현재 글을 쓰고 있는 버전은 2.31.1
이다.
Ubuntu나 Windows10에는 기본적으로 git이 깔리지만 낮은 버전으로 깔린다. 2.3 버전 이후로 명령어의 변화가 있으니 업데이트해주도록 하자.
$ sudo add-apt-repository ppa:git-core/ppa -y
$ sudo apt-get update
$ sudo apt-get install git -y
$ git --version
2.31.1
git config
라는 도구로 설정 내용을 확인하고 변경할 수 있다. Git은 이 설정에 따라 동작한다.
1. /etc/gitconfig: 시스템의 모든 사용자와 모든 저장소에 적용되는 설정이다.
2. ~/.gitconfig, ~/.config/git/config: 해당 사용자에게만 적용되는 설정이다.
3. .git/config: 특정 저장소 내에서만 적용된다.
해당 적용순서는 3 -> 2 -> 1 순서로 우선 적용된다.
사용자 이름과 이메일 주소를 불러와서 적용한다. git은 commit
을 할 때마다 이 정보를 사용한다.
한번 commit
후에는 변경 불가능하다.
$ git config --global user.name "tube-jeonghoon"
$ git config --global user.email "tube@abc.com"
프로젝트마다 다른 이름과 이메일 주소를 사용하고 싶으면 --global
옵션을 빼준다.
해당 명령어로 git 저장소를 만들어준다.
$ git init
이 명령은 .git
에 대한 하위 디렉터리가 있는 디렉터리인 Git저장소를 만든다. .git
디렉터리에는 저장소에 필요한 파일이 들어있다.
다른 프로젝트에 참여하거나 이미 만들어진 git 저장소를 복사하고 싶을 때 git clone
이라는 명령어를 사용한다
git clone
을 사용하면 git history까지 모두 복사해서 온다.
$ git clone https://github.com/tube-jeonghoon/tube-jeonghoon.git
워킹 디렉터리의 모든 파일은 크게 Tracked
와 Untracked
로 나뉘어진다. Tracked
파일은 또 Unmodified
와 Modified
및 Staged
로 나뉘어진다.
git status
명령어를 사용한다.
$ git status
$ git status -s
git status -s
의 -s 옵션은 현재 파일 상태의 간략하게 보여준다.
git add
명령어로 git이 파일을 새로 추적할 수 있다.
$ git add README.md
git add (file) 명령어를 통해 디렉터리에 있는 파일을 추적하고 관리하도록한다. git add 명령은 파일 또는 디렉터리의 경로를 argument로 받는다. 디렉터리면 아래에 있는 모든 파일을 추적한다.
파일 수정 후 git에 추가해보자
첫 번째 유형은
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: README.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: TEST.md
$ git add TEST.md
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: README.md
modified: TEST.md
보통 Tracked
의 파일을 수정하게 되면 "Changes not staged for commit" 상태가 된다. 수정 한 파일이 Tracked
상태이지만 아직 Staged
상태는 아니라는 것이다. git add
명령어로 파일을 다시 추적할 수 있다.
git add
는 세 가지 상황에서 쓸 수 있다.
1. 파일을 새로 추적할 때
2. 수정한 파일을 Staged
상태로 만들 때
3. Merge
할 때 충돌 난 상태의 파일을 Resolve 상태로 만들 때
어떤 내용이 변경되었는지 확인하려면 git diff
명령어를 사용해야 한다.
다음은 Tracked
된 파일을 수정해서 Staged
와 Unstaged
상태 모두 가진 상태이다.
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <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: README.md
이 상태에서 git commit
을 하게 되면 수정되지 않은 README.md가 commit 될 것이다.
무엇이 달라졌는지 확인하자.
$ git diff
diff --git a/README.md b/README.md
index 264dee5..d214cf8 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
wow!
+wow2
(END)
wow2 라는 구문이 추가된 걸 볼 수 있다. 하지만 git add
다시 staged 상태로 만들지 않으면 wow2라는 구문은 commit
되지 않는다. 수정 한 파일을 모두 git add
로 모두 staged 상태로 만들었다면 git diff
명령은 아무것도 출력하지 않는다.
git commit
에 -a 옵션을 주면 staged 상태가 아니더라도 Tracked 상태면 무조건 commit 한다.
git commit -a -m "force commit"
git에서 파일을 삭제하려면 git rm
명령어로 해당 파일을 삭제한 후 commit 해야 한다. 주의사항은 git rm
으로 파일을 삭제하게 되면 실제 데이터도 삭제 되기 때문에 주의해야 한다.
$ git rm untracked.md
rm 'untracked.md'
$ git commit -m "delete untracked.md"
[master 6480c9d] delete untracked.md
1 file changed, 1 deletion(-)
delete mode 100644 untracked.md
하지만 데이터를 남기고 git에서만 지울 수도 있다. git rm --cached
명령어를 쓰면 된다.
$ git rm --cached README.md
rm 'README.md'
$ git status
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
실제 파일은 삭제되어 지질 않았고 Untracked 상태로 바뀌었다.
git에 추가 되어져 있는 파일의 이름을 바꾸고 싶을때는 git mv
명령어를 쓰면 된다.
$ git mv README.md README2.md
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: README.md -> README2.md
git log
를 쓰면 commit history를 조회할 수 있다.
$ git log
commit 4fd6359d1c372c969d7f528a421e94a9367e2f65
Author: jeonghoon-tube <shu7081@gmail.com>
Date: Tue Apr 27 22:12:48 2021 +0900
v2
commit 761994540c0fd3c831765863c2a77e2b8f57810b
Author: jeonghoon-tube <shu7081@gmail.com>
Date: Tue Apr 27 22:11:12 2021 +0900
first commit
(END)
git log
의 대표적인 옵션으로는 -p 옵션과 --stat 옵션이 있다.
-p는 각 커밋의 diff 결과를 보여준다.
$ git log -p -1
commit 9fdea4651f2f7e315ba06fd728bc00222fc61fd3 (HEAD -> master)
Author: jeonghoon-tube <shu7081@gmail.com>
Date: Tue Apr 27 22:37:35 2021 +0900
v3
diff --git a/README.md b/README2.md
similarity index 100%
rename from README.md
rename to README2.md
(END)
-1 옵션은 최근 한개의 결과만 보여준다.
--pretty
옵션도 있다.
$ git log --pretty=oneline
9fdea4651f2f7e315ba06fd728bc00222fc61fd3 (HEAD -> master) v3
6480c9dacd0b78704e82366818d33dea8a508af5 delete untracked.md
4fd6359d1c372c969d7f528a421e94a9367e2f65 v2
761994540c0fd3c831765863c2a77e2b8f57810b first commit
(END)
--pretty
옵션과 자주 쓰는 format 형식의 옵션도 있다.
$ git log --pretty=format:"%h - %an, %ar : %s"
9fdea46 - jeonghoon-tube, 9 minutes ago : v3
6480c9d - jeonghoon-tube, 32 minutes ago : delete untracked.md
4fd6359 - jeonghoon-tube, 34 minutes ago : v2
7619945 - jeonghoon-tube, 36 minutes ago : first commit
(END)
옵션은 밑에 서술하겠다.
옵션 | 설명 |
---|---|
%H | 커밋 해시 |
%h | 짧은 커밋 해시 |
%T | 트리 해시 |
%t | 짧은 트리 해시 |
%P | 부모 해시 |
%p | 짧은 부모 해시 |
%an | 저자 이름 |
%ae | 저자 메일 |
%ad | 저자 시각 |
%ar | 저자 상대적 시각 |
%cn | 커미터 이름 |
%ce | 커미터 메일 |
%cd | 커미터 시각 |
%cr | 커미터 상대적 시각 |
%s | 요약 |
git을 되돌릴 때는 크게 두 가지 방법이 있다. reset
명령어와 revert
명령어이다.
큰 차이점은 현재 버전을 커밋으로 남기는지 안 남기는지의 차이가 있다.
reset
명령어는 현재의 커밋을 남기지 않으면서 이전으로 돌아간다.
예를 들어 로컬저장소에 v1 -> v2 -> v3 이 커밋되어있다. git reset
명령어를 쓰면 v1 -> v2 가 된다.
현재 커밋과 상관없이 강제로 이전 커밋으로 전체를 덮어 써버린다.
$ cat README.md
Hi, my name is version 3
$ git log --oneline
5ee40c3 (HEAD -> master) v3.0
d822cc7 v2.0
68c508b v1.0
$ git reset --hard d822cc7
$ git log --oneline
d822cc7 (HEAD -> master) v2.0
68c508b v1.0
$ cat README.md
Hi, my name is version 2
현재 커밋된 버전의 내용을 둔 채 커밋만 돌아간다.
$ cat README.md
Hi, my name is version 3
$ git log --oneline
5ee40c3 (HEAD -> master) v3.0
d822cc7 v2.0
68c508b v1.0
$ git reset --soft d822cc7
$ git log --oneline
d822cc7 (HEAD -> master) v2.0
68c508b v1.0
$ cat README.md
Hi, my name is version 3 // 커밋은 돌아갔지만 v3의 내용은 남아있다.
revert
명령어는 현재의 커밋을 버전으로 남긴 후 새로운 커밋을 만들면서 돌아간다.
예를 들어 로컬저장소에 v1 -> v2 -> v3 이 커밋되어있다. git revert
명령어를 쓰면 v1 -> v2 -> v3 -> v2 가 된다.
주의 해야 될 사항은 git reset
과는 다르게 돌아 가고싶은 커밋 번호를 적는게 아니라 취소하고 싶은 커밋을 적어줘야 한다.
$ git log
5ee40c3 (HEAD -> master) v3.0
d822cc7 v2.0
68c508b v1.0
$ git revert 5ee40c3
$ git log --oneline
5c6a014 (HEAD -> master) Revert "v3.0"
449c948 v3.0
b34e0c0 v2.0
7c4556d v1.0
2개의 파일이 있는데 모르고 git add .
명령어로 모두 staged 영역에 넣어버렸다.
둘 중에 하나를 빼야 할 때 어떻게 해야 하는가?
$ git add .
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: text1.md
new file: text2.md
"(use "git restore --staged ..." to unstage)" 해당 메시지가 확인된다.
unstaged 영역으로 보내려면 해당 명령어를 입력하라는 뜻이다.
$ git restore --staged text2.md
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: text1.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
text2.md
git 2.23 이전 버전에서는 `git reset HEAD <파일 이름>으로 뺏어야 됐다. 하지만 2.23 이후 버전에서 restore --staged <파일 이름>으로 바뀌였다.
다른 사람들과 함께 일을 하면서 데이터를 원격저장소에 push하고 pull할수 있다.
git remote
명령어로 현재 프로젝트에 등록된 리모트 저장소를 확인할 수 있다.
저장소를 clone 하면 origin이라는 리모트 저장소가 자동으로 등록되기 때문에 origin이라는 이름을 볼 수 있다.
$ git clone https://github.com/tube-jeonghoon/tube-jeonghoon.git
$ cd tube-jeonghoon
$ git remote
origin
새 리모트 저장소는 쉽게 추가할 수 있다. git remote add [단축 이름] [URL]
명령어를 쓰면 된다.
$ git remote add tube https://github.com/tube-jeonghoon/git-test.git
$ git remote -v
tube https://github.com/tube-jeonghoon/git-test.git (fetch)
tube https://github.com/tube-jeonghoon/git-test.git (push)
이제 원격 저장소에서 로컬 저장소로 데이터를 가져올 때 URL 대신에 단축 이름을 사용할 수 있다.
$ git pull tube
Updating bd1e8dd..347ec38
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
git pull
과 git fetch
에는 차이점이 있다. git fetch
는 원격 저장소에 있는 모든 데이터를 로컬로 가져오지만 자동으로 병합(merge) 하지는 않는다. 로컬에서 하는 작업을 모두 마무리하고 수동으로 병합(merge) 해 줘야 한다. 하지만 git pull
은 로컬로 데이터를 가져오면서 자동으로 병합(merge) 한다.
$ git pull tube
Updating bd1e8dd..347ec38
Fast-forward
README.md | 1 +
1 file changed, 1 insertion(+)
프로젝트를 원격 저장소에 올리고 싶을 때 git push
명령어를 사용할 수 있다. 사용 방법은 git push [원격 저장소 이름][브랜치 이름]으로 사용하면 된다.
$ git push tube master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 16 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 288 bytes | 288.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/tube-jeonghoon/git-test.git
347ec38..74ddcfe master -> master
주의 사항으로는 이 방법은 다른 사람이 push 한 뒤에는 push 할 수 없고 원격 저장소에 있는 내용을 가져와(pull) 병합(merge) 한 다음 push 할 수 있다. 자세한 방법은 후술하도록 하겠다.
git remote show [저장소 이름]
으로 해당 저장소의 구체적인 정보를 확인할 수 있다.
$ git remote show tube
* remote tube
Fetch URL: https://github.com/tube-jeonghoon/git-test.git
Push URL: https://github.com/tube-jeonghoon/git-test.git
HEAD branch: master
Remote branch:
master tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
git remote rename
명령어를 사용하면 저장소의 이름을 변경할 수 있다.
$ git remote rename tube wow-tube
$ git remote
origin
wow-tube
git remote rm
명령어로 저장소를 삭제할 수도 있다.
$ git remote rm origin
$ git remote
wow-tube
Git에는 tag를 지원한다. 보통 릴리스할 때 사용한다.
git tag
명령어로 현재 있는 태그를 확인 할 수 있다
$ git tag
Git 태그에는 Annotated 태그와 Lightweight 태그 두 가지 종류가 있다.
브랜치처럼 가리키는 지점을 최신커밋으로 이동시키지 않는다. 단순히 특정 커밋에 대한 포인터 역활만 한다.
$ git tag v1.4-tube
$ git show v1.4-tube
Git 데이터베이스에 태그를 만든 사람의 이름, 이메일과 태그를 만든 날짜, 태그 메시지도 저장하며 -a 옵션과 -m 옵션이 있다. Annotated 태그를 추가할 때 -a를 붙이고 -m으로 태그 메시지도 함께 저장할 수 있다.
$ git tag -a v1.4-tube -m "my version 1.4"
$ git show v1.4
이전 커밋에 태그를 붙일 때가 발생할 수도 있다. git tag -a [태그 이름][커밋 체크 섬]으로 추가할 수 있다. 커밋 체크 섬 값은 길어서 전부 쓸 수 없다면 일부만 적어줘도 된다.
$ git log --pretty=oneline
74ddcfee4306cdfe416764814597a8a0161f1eab (HEAD -> master, tag: v1.4-tube, tag: v1.4, wow-tube/master) add testfile.md
347ec386a0deb178c8f4af00def1ec7c3a93f30c Update README.md
bd1e8dd285d7f1f0ba3d7948888b8dcf8a682c16 first commit
$ git tag -a v1.3 -m "my version 1.3" 347e
$ git log --pretty=oneline
74ddcfee4306cdfe416764814597a8a0161f1eab (HEAD -> master, tag: v1.4-tube, tag: v1.4, wow-tube/master) add testfile.md
347ec386a0deb178c8f4af00def1ec7c3a93f30c (tag: v1.3) Update README.md
bd1e8dd285d7f1f0ba3d7948888b8dcf8a682c16 first commit
Update README.md 커밋에 tag가 성공적으로 붙었다.
명령어를 alias에 등록해 간단하게 쓸 수 있다. git config --global
명령어를 쓰면 된다. 해당 프로젝트에서만 쓰고 싶음면 --global
옵션은 빼도 무방하다.
$ git config alias.st status
$ git st
On branch master
Your branch is up to date with 'wow-tube/master'.
nothing to commit, working tree clean
몇 가지 자주 등록해 두면 편한 단축키이다.
$ git config alias.last 'log -1 HEAD' // 마지막 커밋 출력
$ git config alias.untracked 'restore --staged'
$ git config --global alias.logl 'log --oneline --decorate --graph --all'