git checkout

HEAD가 움직인다.

 


git reset --hard

attached 상태 : HEAD가 가리키는 branch가 움직인다.

detached 상태 : HEAD가 움직인다.

 


fast-forward

* 1f642bb (HEAD -> exp) ex4
* e7790bd ex3
*   a9640d8 (master) Merge branch 'exp'
|\
| * 0b92201 exp 1

위와 같이 exp가 master를 앞서간 상태에서 master에 exp를 merge하면

$ git checkout master; git merge exp
Already on 'master'
Updating a9640d8..1f642bb
Fast-forward
 exp.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

$ git log --oneline --all --graph
* 1f642bb (HEAD -> master, exp) ex4 
* e7790bd ex3 
*   a9640d8 Merge branch 'exp' 
|\   
| * 0b92201 exp 1

Fast-forward라는 로그와 함께 master가 exp에 있는 commit을 가리키게 된다.

새로운 commit을 생성하는 것이 아니라 master의 reference만 변경되는 것이므로 빠르게 동작하므로 fast-forward라고 한다.

 

 

$ git merge --no-ff exp
Merge made by the 'recursive' strategy.
 exp.txt | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
 
$ git log --oneline --all --graph
*   8847542 (HEAD -> master) Merge branch 'exp'
|\
| * 1f642bb (exp) ex4
| * e7790bd ex3
|/  
*   a9640d8 Merge branch 'exp'
|\
| * 0b92201 exp 1

--no-ff 옵션을 사용하면 fast-forward를 사용하지 않고 위와 같이 master와 exp를 부모로 하는 commit을 생성한다.

 


원격저장소

github, bitbucket 등의 원격 저장소를 local pc에서도 생성이 가능하다.

 

원격 저장소 생성

 remote_repo 폴더 생성 후

$ git init --bare 
Initialized empty Git repository in C:/Development/Github/Git6/remote_repo/

로컬 저장소 생성

 local_repo 폴더 생성 후

$ git init 
Initialized empty Git repository in C:/Development/Github/Git6/local_repo/.git/

임의 파일 커밋

$ git commit -am 1
[master (root-commit) 109d6e2] 1
 1 file changed, 1 insertion(+)
 create mode 100644 work.txt

 

 

원격 저장소에 연결

$ git remote add origin ../remote_repo/

(origin은 저장소의 별칭)

 

현재 연결된 원격 저장소 리스트

$ git remote -v 
origin  ../remote_repo/ (fetch) 
origin  ../remote_repo/ (push)

 

원격 저장소가 local의 master를 따르도록 설정

$ git push --set-upstream origin master (git push -u origin master)
Enumerating objects: 3, done. 
Counting objects: 100% (3/3), done. 
Writing objects: 100% (3/3), 213 bytes | 106.00 KiB/s, done. 
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 
To ../remote_repo/ 
 * [new branch]      master -> master 
Branch 'master' set up to track remote branch 'master' from 'origin'.

 

origin/master가 연결된 것 확인.

$ git log --oneline --all --graph
* 109d6e2 (HEAD -> master, origin/master) 1

 

로컬 저장소에 새로운 커밋 

$ git commit -am 2

$ git log --oneline --all --graph
* c772c59 (HEAD -> master) 2 
* 109d6e2 (origin/master) 1

$ git status 
On branch master 
Your branch is ahead of 'origin/master' by 1 commit. 
  (use "git push" to publish your local commits) 

nothing to commit, working tree clean

 

status로 확인시 HEAD가 origin/master(원격) 보다 앞서가고 있으므로 원격으로 push하라는 안내가 나옴.

 

원격 저장소로 push

$ git push 
Enumerating objects: 5, done. 
Counting objects: 100% (5/5), done. 
Writing objects: 100% (3/3), 246 bytes | 82.00 KiB/s, done. 
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 
To ../remote_repo/ 
   109d6e2..c772c59  master -> master

$ git log --oneline --all --graph
* c772c59 (HEAD -> master, origin/master) 2 
* 109d6e2 1

 

remote_repo에서 log 확인

/c/Development/Github/Git6/remote_repo (BARE:master) 
$ git log --oneline --all --graph
* c772c59 (HEAD -> master) 2 
* 109d6e2 1

위와 같이 sync가 맞춰져 local과 동일한 로그가 나오는 것을 확인할 수 있다.

 

새로운 remote_local2 폴더를 만들고 원격 저장소 clone.

/c/Development/Github/Git6/local_repo2    
$ git clone ../remote_repo/ . 
Cloning into '.'... 
done.



$ git log --oneline --all --graph
* c772c59 (HEAD -> master, origin/master, origin/HEAD) 2 
* 109d6e2 1

pull

git pull을 git fetch와 git merge를 합친 명령어이다.

 


cherry-pick

서로 다른 branch에서 특정 commit만 가져와서 반영하고 싶을 때,

 

$ git log --oneline --all --graph
* 2a548b5 (HEAD -> right) R4 
* 21cb3ab R3 
| * 3096289 (left) L4 
| * 0f04059 L2 
|/ 
* 5f0c939 (master) start

위의 상태에서 right R4에 left L2의 commit을 반영하고 싶은 경우,

 

$ git cherry-pick 0f04059
Auto-merging work.txt
[right bef0b4a] L2
 Date: Wed Dec 16 14:34:19 2020 +0900
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --oneline --all --graph
* bef0b4a (HEAD -> right) L2 
* 2a548b5 R4 
* 21cb3ab R3 
| * 3096289 (left) L4        
| * 0f04059 L2 
|/ 
* 5f0c939 (master) start

 

git cherry-pick 'commit id' 를 하면 L2의 Parent를 Base로 L2,R4와 3-way merge가 일어나면서 새로운 커밋이 생성된다.


 

'Git' 카테고리의 다른 글

1일차  (0) 2020.12.15

-a 옵션

tracking중인 파일을 add와 동시에 commit한다. (untracked 파일은 포함되지 않음.)

$ git commit -a -m "work 10"
$ git commit -am "work 10"

git의 commit id는 내용을 기반으로 만들어진다. 

git commit시 일어나는 일. (HEAD -> master인 attached인 경우 기준) 

 

① stage area의 모든 내용을 repository(.git) 으로 copy하고

② message,file,parent를 기반 새로운 hash 값으로 commit id를 생성한다.

③ master는 새로 생성한 commit id가 된다.


HEAD와 master의 차이

master : 마지막(최신) 버전(commit)

HEAD  : working 디렉토리의 버전(commit) (현재 내가 어디있는가?)

 

git log를 치면 HEAD를 찾고 HEAD와 HEAD의 parent들만 추력한다.

master 전체를 보고싶다면 

git log --all

 


git checkout master와 git checkout ("master의 commit id") 차이

case 1.  HEAD -> master : HEAD가 master를 통해 commit을 가리킨다.

$ git checkout master

2ef9f89 (HEAD -> master) work 3 
7aafdd3 work 2 
c30d470 work 1

case 2. HEAD가 직접 commit을 방문한다.

$ git checkout 2ef9f89 

2ef9f89 (HEAD, master) work 3 
7aafdd3 work 2 
c30d470 work 1

 

case 2 상태에서 commit 하게 되면 아래와 같이 HEAD가 뒤쳐지게 된다.

(detached HEAD.. 경고 메시지가 나온다)

$ git log --oneline --all 
b3f0e8d (HEAD, master) work 4 
2ef9f89 work 3 
7aafdd3 work 2 
c30d470 work 1


$ git commit -am "work 5" 
[detached HEAD f222f12] work 5 
 1 file changed, 1 insertion(+), 1 deletion(-)


$ git log --oneline --all 
f222f12 (HEAD) work 5 
b3f0e8d (master) work 4 
2ef9f89 work 3 
7aafdd3 work 2 
c30d470 work 1

 

만약 이상태에서 master로 checkout을 하게되면 commit id f222f12가 사라지게 된다. 

$ git log --oneline --all
b3f0e8d (HEAD -> master) work 4
2ef9f89 work 3
7aafdd3 work 2
c30d470 work 1

최신 버전으로 돌아갈때는 git checkout master 를 사용해야한다.

 

그림 참고

 

Q. Detached 상태에서 commit을 허용하는 이유는?

=> 1. 자유도를 위해서

     2. 실험적인 작업을 테스트 이후 편하게 버리기 위해서. (git checkout master 로 한방에 버릴 수 있다.)

 

$ git log --oneline --all
42e3671 (HEAD) work 7
3734fa2 work 6
ddc9c12 work 5
b3f0e8d (master) work 4
2ef9f89 work 3
7aafdd3 work 2
c30d470 work 1

Q. 만약 위의 상태에서 5,6,7을 버리지 않고 master에 합류시키고 싶다면?

① checkout master (HEAD가 master를 카리키도록 한다, attached)

$ git checkout master
Switched to branch 'master'

$ git log --oneline --all
b3f0e8d (HEAD -> master) work 4
2ef9f89 work 3
7aafdd3 work 2
c30d470 work 1

② reset 42e3671 (master가 work 7을 가리키도록)

$ git reset --hard 42e3671
HEAD is now at 42e3671 work 7

$ git log --oneline --all
42e3671 (HEAD -> master) work 7
3734fa2 work 6
ddc9c12 work 5
b3f0e8d work 4
2ef9f89 work 3
7aafdd3 work 2
c30d470 work 1
  • checkout : HEAD를 움직인다. 

  • reset : master를 움직인다.  (HEAD가 master를 가리키고 있을때만 master가 움직인다. 아닌경우 HEAD가 움직인  다) 

 

 


amend

현재 commit을 수정시에 사용.

수정할 내용을 stage로 올리고 아래 커맨드 입력시 커밋 메시지가 "work 8"로 변경되고 새로운 커밋 id로 교체된다.

$ git commit --amend -m "work 8"

 


 

branch

branch 생성

$ git log --oneline --all
* 0fecf20 (HEAD) work 9
* a718ab9 work 8
* 42e3671 (master) work 7
* 3734fa2 work 6
* ddc9c12 work 5
* b3f0e8d work 4
* 2ef9f89 work 3
* 7aafdd3 work 2
* c30d470 work 1

 

위와 같이 HEAD에서 작업중에 HEAD위치에 exp branch를 생성

$ git branch exp

$ git log --oneline --all
0fecf20 (HEAD, exp) work 9
a718ab9 work 8
42e3671 (master) work 7
3734fa2 work 6
ddc9c12 work 5
b3f0e8d work 4
2ef9f89 work 3
7aafdd3 work 2
c30d470 work 1

 

exp branch로 HEAD checkout

$ git checkout exp

$ git l 
* 4812017 (HEAD -> exp) work exp 10 
* 0fecf20 work 9 
* a718ab9 work 8 
* 42e3671 (master) work 7 
* 3734fa2 work 6 
* ddc9c12 work 5 
* b3f0e8d work 4 
* 2ef9f89 work 3 
* 7aafdd3 work 2 
* c30d470 work 1

이제부터 commit시에 exp branch에 반영된다.

 

 

branch를 이용한 병렬 작업

$ git log --oneline --all 
* 4812017 (HEAD -> exp) work exp 10 
* 0fecf20 work 9 
* a718ab9 work 8 
* 42e3671 (master) work 7 
* 3734fa2 work 6 
* ddc9c12 work 5 
* b3f0e8d work 4 
* 2ef9f89 work 3 
* 7aafdd3 work 2 
* c30d470 work 1

 

위의 상태에서 다시 master로 돌아가서 master에 commit하고 싶다면.

 

① master로 HEAD 이동

$ git checkout master 
Switched to branch 'master'

$ git l 
* 4812017 (exp) work exp 10 
* 0fecf20 work 9 
* a718ab9 work 8 
* 42e3671 (HEAD -> master) work 7 
* 3734fa2 work 6 
* ddc9c12 work 5 
* b3f0e8d work 4 
* 2ef9f89 work 3 
* 7aafdd3 work 2 
* c30d470 work 1

② 'work master 8'을 commit시 아래와 같이 그래프 생성됨.

$ git log --oneline --all
* b1d6eca (HEAD -> master) work master 8 
| * 4812017 (exp) work exp 10 
| * 0fecf20 work 9 
| * a718ab9 work 8 
|/   
* 42e3671 work 7 
* 3734fa2 work 6 
* ddc9c12 work 5 
* b3f0e8d work 4 
* 2ef9f89 work 3 
* 7aafdd3 work 2 
* c30d470 work 1

git checkout exp (master) 로 exp와 master를 오가면서 병렬적으로 작업이 가능하다.

 

 

branch의 실체

 

$ git l 
* 17e1aef (HEAD -> exp, exp2) work 11 mistake 
* 4812017 work exp 10 
* 0fecf20 work 9 
* a718ab9 work 8 
| * a0bcf32 (master) work master 9 
| * b1d6eca work master 8 
|/ 
* 42e3671 work 7

위의 상태에서 아래와 같이 .git/refs/heads 폴더 exp3 파일을 만들고 exp2 파일의 commit id를 exp3에 복사하면

 

 

다음과 같이 exp2와 똑같은 commit을 가리키는 exp3 branch가 생성된다..

즉, branch란 commit id를 담은 파일에 불과한 commit의 포인터이다.

$ git l 
* 17e1aef (HEAD -> exp, exp3, exp2) work 11 mistake 
* 4812017 work exp 10 
* 0fecf20 work 9 
* a718ab9 work 8 
| * a0bcf32 (master) work master 9 
| * b1d6eca work master 8 
|/   
* 42e3671 work 7

 


reflog

git은 어떠한 commit도 삭제하지 않는다.

reflog를 이용하면 이전에 HEAD가 있었던 모든 커밋을 조회할 수 있다.

$ git reflog 
17e1aef (HEAD -> exp) HEAD@{0}: commit (amend): work 11 mistake 
349b4f7 HEAD@{1}: commit (amend): work exp 11 
1b3cdaf HEAD@{2}: commit: work exp 11 mistake 
4812017 HEAD@{3}: reset: moving to 4812017 
a718ab9 HEAD@{4}: reset: moving to a718ab9 
c30d470 HEAD@{5}: reset: moving to c30d470 
a718ab9 HEAD@{6}: checkout: moving from c30d470ffc524b77461c2132f9942fca390b7778 to exp

.......

git reset --hard 349b4f7

or

git reset --hard HEAD@{1}

 

 


merge

브랜치 exp와 master의 내용을 합치고 싶은 경우에 사용한다.

 

만약 master에는 master.txt, exp에는 exp.txt파일이 있을 때,

 

rd HEAD@{1}* 796de53 (HEAD -> exp) work e1 
| * 466c6d0 (master) work m1 
|/ 
* 21b60d9 work 1

위의 상태에서 아래와 같이 git merge exp 명령어를 사용하면.

$ git checkout master
Switched to branch 'master'

$ git merge exp
Merge made by the 'recursive' strategy.
 exp.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 exp.txt
 
 $ git l
*   210c6ad (HEAD -> master) Merge branch 'exp'
|\
| * 796de53 (exp) work e1
* | 466c6d0 work m1
|/
* 21b60d9 work 1

master와 exp를 모두 부모로 가지는 새로운 commit 210c6ad가 생성된 것을 확인할 수 있다.

'Git' 카테고리의 다른 글

2일차  (0) 2020.12.16

+ Recent posts