3 기본
source: categories/study/git-beginner/git-beginner3.md
3.1 Git Lifecycle
-
간단히 add & commit(ci)
- add: 이 파일을 Git이 관리하게 하겠다 (or 수정 완료했다)
- commit: 이 파일을 Git에 저장하겠다
-
Untracked
- Git과 아무 상관이 없는 상태
- 따라서 Git이 대상 파일을 관리하지 못함
- 최초
add
를 해줘야 Git의 관리 대상이 됨
위 이미지에서 Untracked 상태에서add
명령어를 치면 Staged 상태가 되는 것을 볼 수 있다. - Git이 관리하는 파일을 삭제하면 Untracked가 됨
-
Unmodified
- 코드 저장이 완료된 상태
- Staged 상태에서
commit
을 하면 Unmodified가 됨
위 이미지에서 Staged 상태에서commit
명령어를 치면 Unmodified 상태가되는 것을 볼 수 있다.
-
Modified
- Git으로 관리되고 있던 코드를 수정하여 변경이 일어난 상태
- Unmodified 상태인 파일을 수정하면 Modified가 됨
위 이미지를 보면 Unmodified 상태에서 파일 수정만해도 Modified 상태가 되는 것을 확인할 수 있다. commit
할 수 없음.commit
하려면 Staged 상태가 되야함
Staged 상태로 만들기 위해선add
를 해야된다.
-
Staged
- 이제 코드를 저장해도 좋다는(
commit
이 가능한) 상태 - Untracked/Modified 상태인 파일을
add
하면 Staged가 됨
- 이제 코드를 저장해도 좋다는(
3.2 status (st)
현재 Git Lifecycle에서 어떤 상태인지를 알아볼 수 있는 명령어가 git status
이다.
- 현재 git 상태를 보여줌
- Untracked files:
Untracked
상태인 파일들
> echo "status exer" >> st.md
> git status (alias 등록된걸로 하면 git st)
---
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
st.md
nothing added to commit but untracked files present (use "git add" to track)
- Changes to be committed:
Staged
상태인 파일들
> git add st.md
> git status (alias 등록된걸로 하면 git st)
---
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: st.md
- nothing to commit, working tree clean: Unmodified 상태인 파일들
> git commit -m 'Make st.md' (alias 등록된걸로 하면 git ci -m 'Make st.md')
> git status (alias 등록된걸로 하면 git st)
---
On branch master
nothing to commit, working tree clean
- 파일 수정 후 커밋
> vi st.md
> git status (alias 등록된걸로 하면 git st)
---
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
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: st.md
no changes added to commit (use "git add" and/or "git commit -a")
3.3 log(lg)
- 히스토리를 조회하는 명령어
- 커밋 단위로 히스토리가 쌓임
- log를 볼 줄 알아야 develop, release, hotfix 브랜치가 난무할 때 merge 방향이나 순서를 이해할 수 있음
- 위에 있는 것이 최신, 아래 있을 수록 예전 커밋
git lg (alias 등록한 명령어)
---
* ab118e1 - (73 minutes ago) Make st.md - Country
* e5d33ad - (2 days ago) initial commit - Country (origin/master)
3.4 add
-
파일을
Staged
상태로 만듦 -> 파일을 Git이 관리하는 상태로 만듦Untracked
/Modified
상태의 파일에 사용할 수 있음
- 이제
commit
을 하면 코드를 저장할 수 있음 Untracked
에서 진행
echo "## Git class" >> index.md
git st
---
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
index.md
nothing added to commit but untracked files present (use "git add" to track)
git add index.md
git st
---
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: index.md
Modified
에서 진행
vi st.md
git st
---
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: st.md
git add st.md
git st
---
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: index.md
modified: st.md
3.5 commit (ci)
- 파일을
Unmodified
상태로 만듦 -> 한 단위의 작업이 완료 - Git 시스템에 영구적으로 변경을 저장
- SHA-1 알고리즘을 적용한 해시값을 키로 생성.
커밋을 하면 16진수 숫자들이 생성. 이것이 해시키임. - 히스토리가 하나 추가됨
- 실무에서 한 작업 (기능, 피처) 단위로 한 커밋 권장
커밋 단위가 너무 커도 안되고 너무 작아도 안됨.
git ci -m 'Modify files'
---
[master 42298d3] Modify files
2 files changed, 2 insertions(+)
create mode 100644 index.md
git st
---
On branch master
nothing to commit, working tree clean
git lg
---
* 1e928bc - (20 seconds ago) Modify files - Country (HEAD -> master)
* 51462d0 - (4 hours ago) Modify st.md - Country
* ab118e1 - (4 hours ago) Make st.md - Country
* e5d33ad - (2 days ago) initial commit - Country (origin/master)
3.5.1 옵션
-m
: 메시지를 넣음-a
:add
를 같이 함. 단순히 Modified-am
:-a
와-m
을 합친 것. 제일 많이 사용-
--amend
- 마지막 커밋을 수정
Stage
상태의 파일들과 같이 커밋됨- 만약
Stage
에 아무것도 없다면 (commit
이후에 작업을 안했으면) 커밋 메시지만 수정
git lg --- * 1e928bc - (5 minutes ago) Modify files - Country (HEAD -> master) * 51462d0 - (4 hours ago) Modify st.md - Country * ab118e1 - (4 hours ago) Make st.md - Country * e5d33ad - (2 days ago) initial commit - Country (origin/master)
git ci --amend --- [master 69e0e26] Rewrite commit message Date: Mon Mar 9 23:32:31 2020 +0900 2 files changed, 2 insertions(+) create mode 100644 index.md
git lg --- * b0c729f - (6 minutes ago) Rewrite commit message - Country (HEAD -> master) * 51462d0 - (4 hours ago) Modify st.md - Country * ab118e1 - (4 hours ago) Make st.md - Country * e5d33ad - (2 days ago) initial commit - Country (origin/master)
3.6 branch (br)
- 커밋 사이를 가볍게 이동할 수 있는 어떤 포인터 같은 것 (3.1 Git 브랜치 - 브랜치란 무엇인가)
- 하나의 작업 공간 단위 정도로 생각하면 쉬움
- 브랜치 확인:
git br
- 브랜치 생성:
git br test/1
- 브랜치 삭제:
git br -D test/1
git br
---
* master
현재 작업중인 브랜치 앞에 *
이 붙어있음.
현재 브랜치는 master
브랜치 하나가 있고, 현재 내가 작업하고 있는 브랜치는 master
브랜치이다 라는 뜻.
git br test/1
git br
---
* master
test/1
git br -D test/1
---
Deleted branch test/1 (was b0c729f).
-D
대문자 D를 써도되고 소문자 d를 써도 된다.
git br
---
* master
3.7 branch 전략
3.7.1 Git branch 전략 (Git Flow)
Gif Flow 전략
위 사진이 Git Flow 전략을 설명할 수 있는 사진입니다.
위 사진 제일 위에 쓰여있는 것들이 브랜치 이름입니다.
보통 위 5개의 이름을 가진 브랜치들을 사용해 개발을 하게됩니다.
그리고 시간은 아래로 갈수록 지나는 것입니다.
위 사진의 master
브랜치를 보면 Tag 0.1
이 생성되고 거기서 develop
브랜치가 나오고 hotfixes
브랜치가 나오고, 이런 과정들을 쭉 볼 수 있습니다.
-
master
- git init하면 생기는 태초의 브랜치
- 배포 가능한, 말그대로 master 브랜치
- 보통 태그를 따서 태그로 배포함
태그는 보통 위 사진에서도 볼 수 있듯이 0.1버전, 0.2 버전, 1.0 버전 이런식으로 땁니다.
master 브랜치에서 태그 버전을 따서 그 태그를 가지고 배포를 하게됩니다.
보통 master는 중앙 브랜치로 사용하게 됩니다.
즉, 그렇기 때문에 master 브랜치는 어떤 Tag로 롤백을 하더라도 바로 배포가 가능하도록 관리를 해야됩니다.
-
develop
- 보통 작업을 할 때 기준이되는 브랜치입니다.
위 사진에서도 보시면 처음에 master 브랜치에서 develop 브랜치를 생성하고 그 뒤로 많은 일들이 develop 브랜치에서 이뤄지는 것을 보실 수 있습니다. - 개발 서버에도 평소에는 develop 기준으로 배포하며 테스트함.
보통 회사에선 개발서버와 리얼서버로 나뉘어져있는데, 개발서버 같은 경우는 develop 브랜치를 기준으로해서 배포를해서 테스트를 합니다. - 생성위치:
master
(태초)
보통 처음에 master 브랜치로부터 생성됩니다.
- 보통 작업을 할 때 기준이되는 브랜치입니다.
-
hotfix
- 핫픽스는 말 그대로 급하게 고친 버전을 의미하는데 서비스에 문제가 생겨 갑자기 무언가 고쳐서 배포해야할 때 사용합니다. (또는 급하게 기능이 추가되었을 때)
- 생성위치:
master
(그렇지 않으면 다른 작업들이 딸려나감)
위에서도 언급했지만 master 브랜치는 어느 시점이던지 배포해도 아무런 문제가 없도록 관리가 되어야한다고 했습니다.
그래서hotfix
가 발생할 때는develop
에서hotfix
브랜치가 따지는 것이 아니라master
브랜치에서 생성해서hotfix
브랜치를 만들게됩니다. - merge:
master
&develop
그럼hotfix
브랜치에서 고칠 것을 고치고 이제 배포를 해야되는데 그때는master
브랜치로 합치고 또develop
브랜치에도 합쳐줍니다.
develop
에도 해줘야되는 이유는 그래야develop
도master
와 싱크가 맞고 그 상태에서 새로운 작업을 할 때,hotfix
에서 추가된 기능들을 사용할 수 있기 때문입니다.
-
feature
- 실제로 뭔가 기능(feature)를 만드는 브랜치
- 생성위치:
develop
보통develop
브랜치에서 생성합니다. - merge:
develop
(code review)
develop
에서 생성했기 때문에 다시 합칠 때도develop
브랜치로 합쳐줍니다.
그래서 보통 회사에서 일을 할 때는develop
브랜치에서feature
브랜치를 생성해서 거기서 특정 기능을 개발을해서pull request
를 보내서 거기서 코드리뷰를 받고 거기서 승인을 하면develop
브랜치로 합치게됩니다.
-
release
- 새로운 기능들을 추가하여 배포하기 위한 브랜치
- 생성위치:
develop
- merge:
master
&develop
-
이러한 Git Flow 전략 말고도 다른 전략들이 있습니다.
- GitHub Flow, Release Flow …
- 참고: https://newsignature.com/articles/git-branching-strategies-which-one-should-i-pick/
3.7.2 HEAD
- 지금 작업하는 로컬 브랜치를 가리키는 포인터 ((3.1 Git 브랜치 - 브랜치란 무엇인가)[https://git-scm.com/book/ko/v2/Git-%EB%B8%8C%EB%9E%9C%EC%B9%98-%EB%B8%8C%EB%9E%9C%EC%B9%98%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80]{:target="_blank"})
- 현재 브랜치 마지막 커밋의 스냅샷
- branch를 변경하면 해당 브랜치의 마지막을 가리키고 있음
- HEAD를 움직이면서 여러 버전의 코드들을 볼 수 있음
3.8 checkout (co)
- 다른 브랜치로 이동
-
옵션
-
-b
: 브랜치 생성하고 그 브랜치로 checkout- 아래 두 명령은 같음
git co -b develop
git br develop git co develop
-
git co master
3.9 checkout TIP
- 커밋의
hash값
을 알면 시간 여행이 가능함
git lg
---
* b0c729f - (3 hours ago) Rewrite commit message - Country (HEAD -> master)
* 51462d0 - (6 hours ago) Modify st.md - Country
* ab118e1 - (7 hours ago) Make st.md - Country
* e5d33ad - (2 days ago) initial commit - Country (origin/master)
git co e5d33ad
---
Note: checking out 'e5d33ad'.
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 performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b <new-branch-name>
HEAD is now at e5d33ad initial commit
git lg
---
* b0c729f - (3 hours ago) Rewrite commit message - Country (master)
* 51462d0 - (6 hours ago) Modify st.md - Country
* ab118e1 - (7 hours ago) Make st.md - Country
* e5d33ad - (2 days ago) initial commit - Country (HEAD, origin/master)
git br
---
* (HEAD detached at e5d33ad)
develop
master
현재 브랜치는 master
도 아니고 develop
도 아닌 것을 확인할 수 있습니다.
이렇게 옛날 커밋으로 돌아가는 행동을 왜할까?
실무의 경우로 생각해보겠습니다.
- 예전 코드를 확인해야될 때
- 롤백해야될 때
git co master
다시 master
로 돌아갈 수 있습니다.
git br
---
develop
* master
3.10 push
- 로컬 브랜치의 정보를 원격 저장소로 업로드
- Clone 한 리모트 저장소에 쓰기 권한이 있어야 함
- 같은 브랜치로 여러명이 받아서 누군가 push를 했다면 나는 push 안됨
- 다른 사람이 작업한 것을 가져와서 합친 후에 (Merge or Rebase) Push 할 수 있음
git st
---
On branch master
Your branch is ahead of 'origin/master' by 3 commits. (너의 브랜치는 원격 master보다 3커밋이 앞서있다 라는 뜻)
(use "git push" to publish your local commits)
nothing to commit, working tree clean
git lg
---
* b0c729f - (26 hours ago) Rewrite commit message - Country (HEAD -> master, develop)
* 51462d0 - (30 hours ago) Modify st.md - Country
* ab118e1 - (31 hours ago) Make st.md - Country
* e5d33ad - (3 days ago) initial commit - Country (origin/master) // <- 원격 저장소의 master 브랜치는 이 시점에 멈춰있음을 의미합니다.
git co master
git push [origin] [master]
위의 [] 대괄호 표시는 생략 가능하다는 뜻입니다.
-
옵션
-
--force
(-f
)- 내 로컬 브랜치로 원격 브랜치를 덮어 씌워버림
- 내가 혼자 작업하던 feature 브랜치에서만 사용해야함
- 시나리오: 누군가 악의적으로 master브랜치를 망가뜨린다면?
위에서 말씀드렸다시피 Git의 장점은 분산처리. 즉, 어떤 누군가의 로컬에 이전 버전이 남아있다면 복구 가능.
여튼 이러한 위험 때문에 master 브랜치엔 누구나 push할 수 있는 권한을 안줌. 제한을 걸어놓음.
-
3.11 pull, fetch
pull
: Clone 한 서버에서 데이터를 가져오고, 그 데이터를 자동으로 현재 작업하는 코드와 Merge (2.5 Git의 기초 - 리모트 저장소)fetch
: 서버에서 데이터만 가져오고 자동으로 코드를 합치지는 않음
-- 새로운 디렉토리
cd ~
mkdir git-other
cd git-other
git clone 'https://github.com/<깃계정>/<레포이름>.git'
cd git-class
vi README.md
git ci -am 'Modify README.md'
git push
-- 원래 디렉토리
git pull
-- 새로운 디렉토리
cd ~
mkdir git-other
cd git-other
git clone 'https://github.com/<깃계정>/<레포이름>.git'
cd git-class
vi README.md
git ci -am 'Modify README.md'
git push
-- 원래 디렉토리
git fetch
git fetch
를 하면 변경점을 내려받긴하나 합치진 않습니다.
fetch
를 통해 변경점을 확인하신 후에
-- 원래 디렉토리
git pull
git pull
을 하시면 합쳐집니다.
3.12 pull & push 실습
- 환경: master에서 딴 test 브랜치 / 2개의 터미널
-
내용
- fetch vs. pull
-
pull 충돌 실험
<<<<<<< HEAD b222b ======= b111b >>>>>>> eb1e37c
위의
HEAD
는 현재 내 로컬이 가리키는 커밋.
eb1e37c
는origin/test
가 가리키는 커밋.
이 상태에서git merge --abort
명령어를 실행하면git pull
하려고 했던 명령어가 취소됩니다.git merge --abort
git st --- On branch test Your branch and 'origin/test' have diverged, and have 1 and 1 different commits each, respectively. (use "git pull" to merge the remote branch into yours) nothing to commit, working tree clean
그런데 이렇게 항상
--abort
만 할 수 없습니다. 문제를 해결하고merge
하는 것도 해보도록 하겠습니다.b333b
이렇게 충돌 파일을 수정하고
git add a.txt git ci -m 'a.txt resolve conflict' git lg
해결되어 잘
merge
된 것을 확인하실 수 있으실 겁니다. -
branch 삭제
git co master git br -D test git br --- develop <- 로컬에 존재하는 develop 브랜치는 아직 원격저장소에 안올렸기 때문에 원격저장소엔 없습니다. * master
git br -r (remote에 있는 브랜치 확인) --- origin/master origin/test <- test는 로컬에서만 지웠기 때문에 아직 남아있습니다.
git push origin --delete test (원격 저장소에있는 test 브랜치를 지우겠다는 뜻입니다.)
다른 작업자가 브랜치를 삭제해 원격 저장소에 적용해도 내 로컬엔 적용이 안됩니다.git pull
을 해도 삭제된 브랜치가 적용이 안됩니다. 내 로컬엔 그 브랜치가 남아있는 경우가 있습니다.
이럴 경우엔
git fetch -p
명령어를 통해 삭제된 원격 저장소의 브랜치를 로컬에도 반영합니다.-p
는 prune
(가지를 쳐내다)의 약자입니다.
-
추가 명령어
- 파일 변경 내용 보기:
git diff
- 리모트의 브랜치 삭제:
git push origin --delete {branch명}
- 삭제된 리모트 브랜치를 로컬에도 반영:
git fetch -p
- 파일 변경 내용 보기: