Git은 버전 관리 도구로 형상 관리를 지원하며, 개발자들이 협업하거나 소프트웨어 프로젝트를 관리할 때 사용한다.
Git은 소스 코드와 파일의 변경 사항을 관리하고 추적하는 도구로, 소스 코드의 변경 이력을 기록하고 효율적으로 관리할 수 있다.
🔷C드라이브에 git 폴더 생성
git 폴더에 JavaTest 폴더를 생성하고, JavaTest 폴더에는 Hello.java 파일을 생성한다.
🔷git Bash
JavaTest 폴더에서 마우스 오른쪽 클릭, Open Git Bash here를 클릭하여 Git Bash를 연다.
🔷JavaTest 폴더를 Git 관리 대상 등록
$ git init
Initialized empty Git repository in C:/git/JavaTest/.git/
JavaTest 폴더에서 git Bash를 열고, git init 명령어를 입력하면 .git 숨김 폴더 생성가 생성된다.
이는 JavaTest가 Git Repository로 등록된 것을 의미하며, 이때 JavaTest 폴더를 working directory, 작업하는 공간이라고 부른다.
🔷Git 사용자 등록
🔹사용자 등록 (쓰기작업)
$ git config --global user.name "이름"
$ git config --global user.email "이메일"
🔹사용자 등록 확인 (읽기작업)
$ git config --global user.name
$ git config --global user.email
$ git config --global --list
global이 없으면 현재 폴더에만 적용이 되고, global을 붙이면 컴퓨터 전체에서 적용이 된다.
init.defaultbranch=main
사용자 등록 확인을 할 때, 사용자 이름과 이메일 외에도 defaultbranch를 확인할 수 있는데, 이는 git을 설치할 때 옵션으로 Master와 branch 중 선택에 대한 정보이다.
🔷현재 리포지토리 상태 확인
$ git status
On branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
Hello.java
nothing added to commit but untracked files present (use "git add" to track)
status 명령어로 리포지토리의 상태를 확인해보면 생성한 Hello.java 파일이 Untracked 되고 있는 것을 확인할 수 있다. 파일이 추적이 되지 않는 이유는 사용자가 파일을 선택을 하기 전까지는 모두 Untracked 되기 있기 때문이다.
이는 git이 관리하는 폴더에 있음에도 불구하고 Hello.java 파일은 별개임을 의미하며, 사용자는 생성한파일을 git한테 관리할 수 있도록 알려줘야 한다.
참고로 윈도우에서 화면 초기화 명령어는 cls(clear screen)이지만, Git Bash에서 화면을 초기화 할 때에는 clear 명령어를 사용한다. 또한 Git Bash는 tab으로 자동완성 기능을 지원한다.
🔷파일을 Git의 관리 대상으로 등록
$ git add 파일명
$ git add . // 모든 파일
파일은 선택적으로 골라 등록할 경우 '파일명'을 쓰고, 모든 파일을 등록할 경우 '.'을 쓴다.
$ git status
On branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: Hello.java
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: Hello.java
다시 status를 확인해보면 새로운 파일이 등록된 것을 확인할 수 있다.
git 숨김 폴더 내에는 Stage라는 공간이 있는데, add를 하는 순간 Stage 위에 working Directory 내의 파일이 올라간다.
git은 Stage 위에 있는 파일들을 계속해서 모니터링하므로 파일에 변화가 생길 경우 status를 입력했을 때 modified 되었다고 알려주고, 삭제했을 경우 deleted 되었다고 알려준다.
🔷파일을 Git의 관리 대상에서 해제
$ git rm --cached 파일명
$ git rm --cached -f Hello.java
rm 'Hello.java'
캐시에서 해제하여 파일이 추적이 안 되는 상태로 돌아가게 할 수 있다.
🔷커밋 생성하기
$ git commit -m '메시지'
$ git commit -m 'Init. Add Hello.java'
commit은 특정 시점의 리포지토리 상태를 저장하는 행동이다. (백업 파일 생성)
ex)백업파일(2023_08_16_개인복습.zip)
리포지토리의 관리되는 모든 파일을 백업을 할 때, 시간은 git에서 알아서 저장을 해 주지만, 사용자가 이름(메시지)을 직접 지정해 주어야 한다.
나중에는 커밋이 수백개가 되므로, 이 메시지는 알아보기 쉽게 해야 하며, 커밋 메시지 작성 요령(패턴)이 있다.
🔷커밋 이력 확인
$ git log
commit c130e11f620053e34122322781bcc5b04364a4c4 (HEAD -> main)
Author: 이름 <이메일>
Date: Wed Aug 16 09:43:20 2023 +0900
Init. Add Hello.java
got log 명령어를 입력하면 커밋 식별자와 커밋을 만든 사람과 만든 날짜, 그리고 커밋이 어떤 내용을 가지고 있는지를 확인할 수 있다.
$ git log --oneline
c130e11 (HEAD -> main) Init. Add Hello.java
나중에 커밋이 많아지면 로그 확인이 어려우므로, --oneline 명령어를 추가하여 한 줄로 보는 경우가 많다.
🔷커밋 수정
🔹둘째날 (파일 수정)
$ git add Hello.java
$ git commit -m 'Modified Hello.java'
[main 3b7ee0b] Modified Hello.java
1 file changed, 4 insertions(+), 1 deletion(-)
둘째날에는 기존에 생성한 Hello.java 파일을 수정하여 파일을 다시 add하고 새로 커밋을 진행했다.
$ git log --oneline
3b7ee0b (HEAD -> main) Modified Hello.java
c130e11 Init. Add Hello.java
log를 확인해 보니 마지막 커밋만이 아닌 해당 리포지토리에서 있었던 과거의 커밋까지 모두 보여주는 것을 확인했다.
가장 마지막의 커밋에는 (Head -> main) 표시가 붙어 있는데, 이는 마지막에 한 커밋이라는 걸 알려주기 위한 표시이다.
🔹셋째날 (파일 생성)
셋째날에는 폴더 내에 새로운 Item.java 파일을 생성했다.
$ git status
On branch main
Untracked files:
(use "git add <file>..." to include in what will be committed)
Item.java
nothing added to commit but untracked files present (use "git add" to track)
파일을 생성하자 폴더에 Untracked 파일이 생겼다.
이제 Item.java 파일을 Stage 위에 올리는 작업을 해야 한다.
$ git add Item.java
$ git status
On branch main
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: Item.java
Item.java 파일을 등록한 뒤 status를 확인해보니 new file: Item.java 된 것을 확인할 수 있다.
$ git commit -m 'Add Item.java'
[main 7415e7f] Add Item.java
1 file changed, 6 insertions(+)
create mode 100644 Item.java
파일 생성이 일어났으니 새로운 커밋을 진행한다.
🔹넷째날 (커밋 회귀)
$ git status
On branch main
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: Item.java
no changes added to commit (use "git add" and/or "git commit -a")
$ git add .
$ git commit -m 'Modified Hello.java,Item.java'
[main 23c7ba6] Modified Hello.java,Item.java
1 file changed, 3 insertions(+), 6 deletions(-)
$ git log --oneline
23c7ba6 (HEAD -> main) Modified Hello.java,Item.java
7415e7f Add Item.java
3b7ee0b Modified Hello.java
c130e11 Init. Add Hello.java
넷째날에는 Hello.java와 Item.java 수정하여 모든 파일에 add를 진행했다.
그런데 아차차, Hello.java 수정 실수가 있었다! 이때 이전 커밋으로 돌아가는 방법으로 파일을 되돌릴 수 있다.
이전 커밋으로 돌아가는 방법은 revert와 reset을 사용하는 방법이 있다. 먼저 reset을 사용하는 방법에 대해 알아보도록 하자.
reset 커밋 돌아가기 (mixed)
$ git reset 커밋식별자(커밋ID)
$ git reset 7415e7f
$ git reset --mixed 7415e7f
git log를 확인하여 돌아갈 위치의 커밋식별자를 입력해준다.
이때 mixed 방식이 reset의 기본 기능이므로, --mixed는 생략해도 된다.
Unstaged changes after reset:
M Item.java
reset을 했음에도 잘못 수정한 내용이 그대로 남아있는 것을 확인할 수 있는데, 이는 mixed 방식의 특징이다.
커밋만 이전의 상태로 돌아가고, 수정한 상태는 그대로 남아있다. 이처럼 내용은 그대로 남아 있으니 사용자에게 수정한 내용을 직접 확인하여 지울 수 있는 여지를 주는 것이다.
$ git add .
$ git commit -m 'Modifed Hello.java, Item.java'
만약 잘못 수정했다고 생각했던 내용을 그대로 남길 경우, 다시 커밋을 진행하면 된다.
reset 커밋 돌아가기 (hard)
$ git reset --hard 7415e7f
HEAD is now at 7415e7f Add Item.java
reset으로 커밋을 되돌리는 또 다른 방법으로는 hard 방식이 있는데, 이 방식으로 reset을 하면 소스코드가 이전의 상태로 완전히 돌아가 있다.
hard로 커밋을 되돌리면 내가 무엇을 수정했는지 알기 어렵다. mixed 방식이 수정하기에 더 이점이 있으므로 mixed 방식을 많이 사용하는 편이다.
🔹다섯째날 (커밋 회귀)
$ git add Item.java
$ git commit -m 'Modified Item.java'
[main e9dd37e] Modified Item.java
1 file changed, 4 insertions(+), 5 deletions(-)
다섯째 날에는 Item.java 파일을 수정했다.
이때 아차차, Item.java 파일에 실수가 있었다! 그래서 Item.java 파일을 되돌리려고 한다.
이번에는 revert 기능을 이용하여 되돌려보도록 하자.
$ git log --oneline
e9dd37e (HEAD -> main) Modified Item.java
7415e7f Add Item.java
3b7ee0b Modified Hello.java
c130e11 Init. Add Hello.java
먼저 log 명령어를 통해 돌아갈 커밋ID를 확인한다.
$ git revert 커밋생성자(커밋ID)
$ git reset 7415e7f
Unstaged changes after reset:
M Item.java
$ git status
On branch main
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)
Revert "Modified Item.java"
This reverts commit e9dd37e8bca2d8b13e7d7c538d100efa80d9b5b7.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch main
# Changes to be committed:
# modified: Item.java
#
revert 방법으로 커밋을 돌아갈 때에는 커밋생성자에 내가 없애고 싶은 커밋을 적는다.
혼자 작업을 할 때에는 reset과 revert 기능 중 무엇을 사용해도 상관이 없다. 그러나 팀 작업은 reset을 하면 안 된다. 팀 작업을 할 때 reset을 해버리면 버전 하나를 뒤로 되돌렸다는 사실을 모르게 된다.
revert는 과거로 돌아갔던 사실도 같이 공유가 되기 때문에 상황을 이해하기 쉬워지며, 같은 자원을 건드렸을 때 충돌이 날 확률이 떨어진다.
🔷커밋간 이동
$ git checkout 커밋생성자
$ git checkout 3b7ee0b
checkout 명령어를 통해 커밋간에 이동할 수 있다.
Note: switching to '3b7ee0b'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:
git switch -c <new-branch-name>
Or undo this operation with:
git switch -
Turn off this advice by setting config variable advice.detachedHead to false
HEAD is now at 3b7ee0b Modified Hello.java
$ git reflog
3b7ee0b (HEAD) HEAD@{0}: checkout: moving from main to 3b7ee0b
6e08cf8 (main) HEAD@{1}: revert: Revert "Modified Item.java"
e9dd37e HEAD@{2}: commit: Modified Item.java
7415e7f HEAD@{3}: reset: moving to 7415e7f
d1695c8 HEAD@{4}: commit: Modifed Hello.java, Item.java
7415e7f HEAD@{5}: reset: moving to 7415e7f
23c7ba6 HEAD@{6}: commit: Modified Hello.java,Item.java
7415e7f HEAD@{7}: commit: Add Item.java
3b7ee0b (HEAD) HEAD@{8}: commit: Modified Hello.java
c130e11 HEAD@{9}: commit (initial): Init. Add Hello.java
이력이 남아있지 않아서 커밋 간에 이동할 수 없는 경우, reflog 명령어를 통해 log를 확인할 수 있다.
$ git checkout 6e08cf8
Previous HEAD position was 3b7ee0b Modified Hello.java
HEAD is now at 6e08cf8 Revert "Modified Item.java"
커밋은 만에 하나 문제가 생길 경우를 생각하여 드는 보험이라고 생각하면 된다.
변화가 생길 경우 커밋을 하지만, 대부분의 커밋은 사용되지 않는다.