이 시리즈는 git에 대해서 아무것도 모르는 사람을 위한 글이 아니다. 분명 학생이었을 때는 열심히 배웠다가, 현업에 들어가서 몇 년동안 비슷한 명령어만쳤던 재활 훈련자를 위한 글이다.
git을 처음 시작할 때는 git init
으로 시작하도록 한다.
git init
이 다음 .git
directory가 우리의 project에 만들어졌을 것이다.
ls -a .git
. .. branches COMMIT_EDITMSG config description HEAD hooks index info logs objects refs
git status
를 통해서 현재 project의 git상태를 확인할 수 있다.
git status
On branch master
nothing to commit, working tree clean
다음과 같이 나왔다면 project의 .git
과 상호작용이 되고 있는 것이다.
참고로 .git
이 생긴 directory 아래로 모든 file, directory는 git
의 영역 안에 있는 것이다. 따라서, .git
이 있는 project안에 새로운 directory를 만들어서 또 git init
을 할 수는 없다.
-------------------
|Working Directory|
-------------------
|
git add
|
--------------
|Staging Area|
--------------
|
git commit
|
------------
|Repository|
------------
각각의 code checkpoint를 git에서 commit으로 관리하는 것이다.
이들은 3개의 물리적인 영역이 아니라, 가상의 공간이다.
git add
로 올린다. .git
directory를 말한다. 여기에 변경 사항들이 저장된다. git commit
으로 repo에 저장한다.만약 working directory에 README.md 파일이 있다면 git status
에 다음과 같이 나온다.
git status
On branch master
No commits yet
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)
git add
를 통해서 staging area로 올려주도록 하자. 이 다음 git status
를 확인하면 다음과 같다.
git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
staging area에 있다는 것을 알 수 있다.
git commit
시에는 항상 commit에 대한 설명을 같이 넣어주어야 한다. git commit
명령어 후에 에디터를 통해서 설명을 넣어주면 되는데, git commit -m ""
으로 간단하게 메시지를 남길 수 있다.
git commit -m "add README.md"
[master (root-commit) ecba3bc] add README.md
1 file changed, 42 insertions(+)
create mode 100644 README.md
다음으로 git status
를 쓰면 다음과 같이 나온다.
git status
On branch master
nothing to commit, working tree clean
더 이상 working directory에 변경된 부분이 없다는 것이다.
git log
를 사용하면 repository에 대한 정보를 얻을 수 있다.
git log
commit 1b624a2c0874b8cdb9aa8ffaf4c9b6110b3ef489 (HEAD -> master)
Author: colt <colt@colt.com>
Date: Wed Jul 31 14:34:36 2024 +0900
add README.md
commit ecba3bcc49a2c1691015ecf07139bb903e40f3e1
Author: colt <colt@colt.com>
Date: Wed Jul 31 14:33:41 2024 +0900
add README.md
다음과 같이 우리가 commit한 사항들이 나오는데, 이는 .git
directory에 기록된 repository 정보라서 나오는 것이다.
git commit을 atomic하게 다루는 것이 좋은데, atomic하게 다룬다는게 무슨말인가?? atomic하게 다루라는 말은 git commit을 더 이상 쪼갤 수 없을 만큼 작게 다루라는 것이다. 즉, commit 한 가지에 한 가지 기능만 집중하라는 것이다.
또한, commit msg는 '현재 시제'를 써야한다. 이는 docs에서 추천하는 방법이다. 즉 changed
맏고 change
를 쓰라는 것이다. 그런데, 이는 실제 개발을 할 때 매우 애매하다. 왜냐하면 '현재 시제'는 하고 있는 느낌이고 '과거 시제'가 이미 commit한 내용에 대한 설명을 하고 있기 때문이다.
따라서, commit msg에 대해서는 자신이 속한 기관, 오픈소스 프로젝트의 commit style을 따르거나, 자신만의 확실한 이유가 있어야 한다.
만약 git commit
시에 나오는 editor가 너무 어려우면 다음의 명령어를 통해서 editor를 바꿀 수 있다.
git conig --global core.editor "vim"
위의 code는 vim이고 아래의 code는 vs code로 바꾸는 것이다.
git conig --global core.editor "code" --wait
추가적인 설정 방법은 아래를 참고하면 된다.
https://git-scm.com/book/en/v2/Appendix-C%3A-Git-Commands-Setup-and-Config
commit을 시킨 후에 다음과 같은 이유로 수정을 하고싶을 때가 있다.
이런 경우에 git commit --amend
를 사용하여, repository에 있는 최신 commit을 수정할 수 있다.
가령 다음과 같은 경우가 있다.
git add .
git commit -m "some commit"
그런데, review해보니 forgotten_file
을 누락하여서, 새로 생성 후에 stage에 넣어준다.
git add forgotten_file
이 다음은 새로운 commit을 만들어야 할까? 이전 commit에 해당하는 내용이기 때문에 새로운 commit을 만들고 싶진 않다. 어떻게 해야할까?? 이때 사용하는 것이 바로 git commit --amend
이다.
git commit --amend
--amend
는 이전 commit을 취소하여 이전 commit의 내용과 현재 stage 내용을 바탕으로 새로운 commit을 하나 만드는 것이다. 이 과정에서 commit msg를 수정할 수도 있다.
따라서, git commit --amend
를 사용하여 repository에 있는, 최근의 commit에 대해서 수정할 수 있는 것이다.
git log
를 사용하면 이런저런 commit들이 쭈룩 나오는 것을 볼 수 있다.
git log
commit 021927702020a86ec4d2c5bd0703a852bbf50339 (HEAD -> master)
Author: colt <colt@colt.com>
Date: Wed Jul 31 14:51:45 2024 +0900
feat: update .gitignore
commit 4f8b7e406703ef2cc81a87689fafcae86c9af37a
Author: colt <colt@colt.com>
Date: Wed Jul 31 14:49:25 2024 +0900
add .gitignore
...
너무 많고, verbose하기 때문에 필요한 정보를 얻기가 힘들다. 따라서, 필요한 정보를 얻기 편하도록 oneline으로 바꾸는 것이 있는데, 이것이 oneline
옵션이다.
git log --oneline
0219277 (HEAD -> master) feat: update .gitignore
4f8b7e4 add .gitignore
1b624a2 add README.md
ecba3bc add README.md
사실 git log에는 이런저런 option들이 많은데, 굳이 모두 다 사용할 필요는 없다.
branch는 commit의 연결을 나누는 분기가 된다.
--------> (commit4) [test branch]
|
(commit1) ---> (commit2) ---> (commit3) [master branch]
이렇게 branch를 나누고, branch를 서로 merge시켜주는 작업이 반복되는 것이 git의 업무이다.
--------> (commit4) -------->| [test branch]
| merge
(commit1) ---> (commit2) ---> (commit3) ---> (commit5) [master branch]
가장 기본적으로 사용되는 branch가 master
branch인데, master
branch는 git
에서 사용되는 기본 branch로 가장 근간이 되는 branch로 생각하면 된다. github
의 경우는 2020이후에 main
branch로 바꾸었는데, 이는 github
기준이다.
git log
를 사용하면 현재 무슨 branch인지를 볼 수 있다.
git log --oneline
aa83f2c (HEAD -> master) feat: update .gitignore
4f8b7e4 add .gitignore
1b624a2 add README.md
ecba3bc add README.md
master
라는 것을 알 수 있다. 그런데, HEAD
는 무엇일끼?? 이를 'branch reference'라고 하는데, 이는 현재의 branch의 가장 최근 commit을 말하는 것이다.
--------> (commit4 - HEAD) [test branch]
|
(commit1) ---> (commit2) ---> (commit3) ---> (commit5 - HEAD) [master branch]
test branch의 가장 최근 commit인 commit4
가 test branch의 HEAD이고, commit5
는 master branch의 HEAD가 되는 것이다.
그래서 git log
시에 가장 최근의 commit을 HEAD라고 표시한 것이다.
이제 git branch
를 사용해서 현재 repository에 어떤 branch들이 있는 지 확인해보도록 하자.
git branch
* master
현재 master
밖에 없다. 새로운 branch를 만들기 전에 playlist.txt
파일을 만들고 추가해보도록 하자.
SONG - ARTIST
=============
playlist.txt
를 만들고, 이를 stage에 넣고 repository로 commit해주도록 하자.
git add ./playlist.txt
git commit -m "add playlist.txt"
git log
commit 193ea6f7130f743ee87fe109870ebbdb8eb2538c (HEAD -> master)
Author: colt <colt@colt.com>
Date: Wed Jul 31 16:20:29 2024 +0900
add playlist.txt
...
새로운 branch를 만들어보도록 하자.
git branch <branch-name>
bugfix
라는 branch를 생성해보도록 하자.
git branch bugfix
확인해보도록 하자.
git branch
bugfix
* master
제대로 생성된 것을 볼 수 있다. 그런데 *
가 master
에 있는 것을 볼 수 있는데, master
의 branch에 있다는 것을 의미한다.
이제 bugfix
branch로 옮겨보도록 하자. 이전에는 git checkout
을 사용했지만, 이제는 git switch
를 사용한다. 사용 방법은 다음과 같다.
git switch <branch-name>
bugfix
branch로 옮겨보도록 하자.
git switch bugfix
Switched to branch 'bugfix'
이제 HEAD
는 master branch가 아니라 bugfix branch를 가리킨다.
git log
commit 193ea6f7130f743ee87fe109870ebbdb8eb2538c (HEAD -> bugfix, master)
Author: colt <colt@colt.com>
Date: Wed Jul 31 16:20:29 2024 +0900
add playlist.txt
...
HEAD
가 bugfix와 master를 가리키는 것을 알 수 있다. 이는 bugfix
와 master
의 최근 commit이 동일한 것이라는 걸 알려주고 있다.
이제 몇 가지 새로운 code를 추가하기 위해서 playlist.txt
를 수정해보도록 하자.
SONG - ARTIST
=============
DEAN - what2do
NEWJEANS - Super Shy
stage에 넣고 repository로 commit을 시켜주두록 하자.
git add ./playlist.txt
git commit -m "update playlist.txt"
이제 git log
를 통해서 HEAD
가 어디에 있는 지 확인해보도록 하자.
git log
commit f002b8fa14f0056fd77eb5f7f17972a98a029553 (HEAD -> bugfix)
Author: colt <colt@colt.com>
Date: Wed Jul 31 16:29:47 2024 +0900
update playlist.txt
commit 193ea6f7130f743ee87fe109870ebbdb8eb2538c (master)
Author: colt <colt@colt.com>
Date: Wed Jul 31 16:20:29 2024 +0900
add playlist.txt
...
master
의 commit과 분리되어 HEAD
가 bugfix
만 가리키는 것을 볼 수 있다.
다시 master branch로 이동해보면, bugfix
에 추가했던 DEAN - what2do
와 NEWJEANS - Super Shy
가 playlist.txt에 없을 것이다.
git switch master
cat ./playlist.txt
SONG - ARTIST
=============
git checkout
역시도 git switch
처럼 branch를 이동할 수 있는데, git checkout
이 이전부터 사용되어 아직도 많이 사용되고 있다. 그러나 git checkout
은 너무나 많은 기능들을 담당하고 있기 때문에 git checkout
대신에 git switch
가 등장한 것이다.
git checkout
역시도 branch 이동이 가능하다.
git checkout <branch-name>
또한, 가장 많이 사용되는 것 중 하나가 branch를 생성함과 동시에 이동하는 명령어로 -b
옵션을 사용하면 된다.
git checkout -b <branch-name>
이 기능은 switch
에서도 제공해주는데, -b
가 아니라 -c
로 create 옵션이라는 것이다. 즉, 새로운 branch를 create하고 이동하겠다는 것이다.
git switch -c <branch-name>
checkout은 그 의미도 기능도 매우 모호하지만 switch는 매우 명시적이다.
현재 master
branch에 있다고 하자. 여기서 playlist.txt
파일을 수정해보도록 하자.
SONG - ARTIST
=============
eqweqwewqew
그러나 git add
를 통해서 playlist.txt
파일을 staging시키지 않고, branch를 이동시키려고 한다면 어떤 문제에 봉착할까? 이전에 만든 bugfix
branch로 이동해보도록 하자.
git switch bugfix
error: Your local changes to the following files would be overwritten by checkout:
playlist.txt
Please commit your changes or stash them before you switch branches.
Aborting
거부당하게 되는데, error 로그를 잘 보면 playlist.txt
가 수정되었지만 staging area에 없기 때문에 다른 branch로 이동시 삭제됨으로 처리하라는 것이다.
이를 해결하기위해서는 staging area에 넣고 commit해야한다.
git add ./playlist.txt
git commit -m "update playlist.txt"
git switch bugfix
Switched to branch 'bugfix'
bugfix
로 branch가 옮겨지는 것을 볼 수 있다.
이렇게 branch를 이동하기 전에 특정 file을 수정했다면 commit
후에 branch를 이동하는 것이 좋다.
그런데, 만약 file을 새로 만드는 경우는 어떻게 되는가?? moon.txt
를 하나 만들어보도록 하자.
hello moon
이 상태에서 branch를 이동해보도록 하자.
git switch master
Switched to branch 'master'
문제없이 이동되는 것을 볼 수 있을 것이다. 이처럼 새로운 파일을 추가하는 것은 어떤 branch를 이동하던간에 commit
을 하지 않아도 따라가게 된다.
삭제를 하기 위해서 쓸모없는 branch를 하나 만들어보자.
git switch -c deleteMe
git branch
bugfix
* deleteMe
master
branch를 삭제할 때는 -d
또는 --delete
를 사용하면 된다.
git switch master
git branch -d deleteMe
Deleted branch deleteMe (was 204aed7).
만약, 병합 상태가 해결되지 못했다면 -d
를 사용해도 삭제되지 않는다. 강제로 삭제하는 방법이 있는데, -D
를 사용하면 된다. 이는 --delete --force
의 단축어이다.
다음으로는 branch의 이름을 변경하는 벙법인데 -m
또는 --move
옵션을 사용한다. 이름을 바꾸려는 branch에 가서 git branch -m <바꾸고 싶은 이름>
을 쓰면 된다.
git switch -c recent
recent
branch의 이름을 lately
로 바꾸자.
git branch -m lately
git branch
bugfix
* lately
master
바뀐 것을 볼 수 있다.