본문 바로가기

Git

Git - 동작 정리 (기본편)

- 원격 저장소와 로컬 저장소

Git은 원격 저장소와 로컬 저장소 두 종류의 저장소를 제공

    - 원격 저장소(Remote Repository): 파일이 원격 저장소 전용 서버에서 관리되며 여러 사람이 함께 공유하기 위한 저장소.

    - 로컬 저장소(Local Repository): 내 PC에 파일이 저장되는 개인 전용 저장소

 

- 커밋 (commit)

: 파일 및 폴더의 추가/변경 사항을 저장소에 기록한다.

  일반적으로, 우리가 작업한 내용은 저장(Save)하는 개념이며 Git Branch에서 하나의 작업단위가 될 것이다.

 

(!) 여기서 stage영역이란?

: 실제로 커밋을 진행하기 위해 준비하는 공간이라고 생각하면 된다. 그 반대로는 unstage영역이라고 하는데, 파일이 변경은 되었지만 커밋은 하지않는 영역이다.

 

(stage 공간에 대한 이해 참고 예시)

위에는 unstage영역에, 아래는 stage영역에 등록되어있는 상태이다.

[command]

$ git status

: 현재 추적하고있는 branch 확인 & 작업 변경사항 or 충돌내용 등 상태확인 명령

 

$ git add [파일경로]

: 변경내용 stage에 등록

(!) 파일경로에 * 를 입력하면, 변경내용이 있는 파일들 모두 stage영역에 올라간다.

 

$ git reset HEAD [파일경로]

: stage에 등록된 변경파일을 unstage로 내린다.

 

$ git commit -m "커밋 메시지"

: stage에 등록된 변경파일 (커밋 메시지를 입력하여) 커밋진행

 

- 푸시 (push)

: 로컬저장소에 커밋한 내용들을 원격 저장소에 저장하는 행위. 원격 저장소에 푸시가 진행되면, 다른 개발자가 내가 작업한 내용을 공유받아서 사용할 수 있게 된다.

 

커밋 - 원격저장소 푸시 과정

 

커밋(master) & 푸시가(origin/master) 완료된 상황

[command]

$ git push origin [브랜치명]

: 로컬저장소에 변경내역(커밋)이 존재하는 상태에서 원격저장소에 반영 요청

 

(!) 내가 push하기전에 다른 개발자가 이미 push를 진행했을 경우, 오류가 출력되면서 push요청이 거절될 수 있다. 이때는 다른 작업자의 작업내용을 pull하여 update를 진행한 뒤에 push를 하도록 하자.

- 클론 (clone)

원격 저장소를 복제해온다.

[command]

$ git clone [복사할 프로젝트 주소] [디렉토리명 (옵션)]

: 로컬저장소에 저장되는 경로는 현재 내가 위치해 있는 경로(pwd)

 

(!) 저장소 만들기 (init)

: git이 설치가 되어있어야한다.

저장소를 만드는 상황은 온프로미스 환경에서 직접 원격저장소에 프로젝트를 생성하는 등의 경우에 사용하며,

대부분 github, gitlab, bitbucket 등.. 원격저장소(웹)에서 프로젝트를 생성해서 clone으로 진행하는 방법을 선호한다.

 

[command]

$ git init

 

- 풀 (pull)

: 원격저장소에서 로컬저장소로 업데이트를 진행한다. (다른 인원이 원격저장소에 push를 한 내용을 pull 한다)

 

[command]

$ git pull origin [브랜치명]

: 로컬브랜치에 checkout되어있는 브랜치 기준으로 원격저장소의 내용을 가져온다.

 

- Checkout

: 내가 사용할 브랜치를 지정.

[command]

$ git checkout [브랜치명]

 

- 병합 (Merge)

: 다른 브랜치를 현재 checkout된 브랜치에 병합하는 명령이다.

 

[command]

$ git merge [대상 브랜치명]

 

iss53 브랜치가 master브랜치에서 분기하여 작업이 진행
master브랜치에서 iss53 브랜치를 merge하였다.

=> git checkout master / git merge iss53 명령어를 내려서 master브랜치에 iss53브랜치를 병합하였다. 이때, C6이라는 새로운 merge commit이 새로 생성되며 iss53 변경내용이 master에 적용된다.

 

(!) merge 진행시 코드 충돌(conflict)이 발생하는 경우

git merge [브랜치명] 명령어로 merge하다가, 서로다른 브랜치에서 수정영역이 발생하는경우에 충돌이 일어나는 상황이 있다.

$ git merge iss53
Auto-merging src/main/Main.java
CONFLICT (content): Merge conflict in src/main/Main.java
Automatic merge failed; fix conflicts and then commit the result.

=> merge를 시도했는데, 위와같은 결과물이 나온다면 자동으로 Merge를 하지 못해서 새 커밋이 생성되지 않는다. 이 충돌내용을 개발자가 직접 해결하지 않는이상 더이상 진행할 수 없다. 따라서 충돌부분을 수정해주고

$ git add [파일명]

명령어를 통해 다시 stage에 등록하여 commit을 진행해준다.

(충돌이 발생했을 경우 <<<<<< , ======, >>>>>> 와 같은 포인트가 생겨난다. 충돌로 생겨난 이 문자들을 그대로 stage에 올려서 충돌을 해결하면 컴파일오류가 발생하므로, 반드시 주의할 것!!)

(참고: backlog.com/git-tutorial/kr/stepup/stepup2_7.html)

- 브랜치(branch)란?

: 독립적으로 어떤 작업을 진행하기 위한 개념. 나무가 있다고 했을때 중심기둥이 있고 중간중간에 가지가 뻗어나가고 있는데 그 가지와 비슷한 느낌이다. 브랜치가 만들어져서 분기하여 독립적인 작업을 진행하다가 나중에 merge를 통해 합쳐질 것이다.

(merge부분 그림 참조)

 

[command]

$ git branch [(옵션)]

: 로컬 저장소의 브랜치 목록을 불러온다.

 

(!) branch (옵션)

-v : 로컬 branch의 정보를 마지막 커밋 내역과 함께 보여줌

-r : 리모트 저장소의 branch 정보를 노출

-a : 로컬/원격 저장소의 모든 branch 정보를 노출

[브랜치명] : 브랜치 생성 + checkout

--merged : checkout한 기준 브랜치에서 merge가 된 branch를 표시.

--no-merged : checkout한 기준 브랜치에서 merge가 되지 않은 branch를 표시.

-d [브랜치명] : branch를 삭제한다.

    => merge가 되지않은 브랜치는 삭제가 안되며 강제로 삭제할 경우에는 -D(강제삭제 옵션)을 사용하여 제거한다.

    => 당연한거지만 현재 checkout중인 브랜치를 삭제할 수 없다. (내가 밟고있는 종이를 치울 수 없는 것 처럼...)

-m [변경할 브랜치명] [변경될 브랜치명] : 브랜치명을 변경한다.

 

- stash (임시저장)

: 마무리 하지 않는 작업을 스택에 잠시 저장할 수 있도록 한다. 즉 commit을 하지않고 로컬 스택에 임시 저장된다.

stash에 저장되는 파일

  • modified이면서 Tracked(추적) 상태인 파일
  • stage에 있는 파일 (추적중이지 않은 파일도 포함)

[command]

$ git stash [옵션]

(!) stash 옵션

save : (=git stash와 동일)

list : stash 목록을 확인할 수 있다.

apply [stash 이름]: stash 내용을 가져온다. 이때 unstaged 상태로 복원한다. (default 가장 위의 stash 내용)

apply --index : index옵션이 적용되면, staged 였던 상태까지 복원해준다.

drop [stash 이름] : apply는 적용은 되지만, stash 스택을 삭제까지 해주지는 않는다. drop 명령어를 통해 스택에서 제거할 수 있다. (default 가장 위의 stash 내용)

pop [stash 이름] : apply와 drop 동작을 한번에 수행한다. (default 가장 위의 stash 내용)

clear : stash 내용을 모두 제거한다.

 

- rebase (리베이스)

: 말그대로 base를 재배치하는 작업.

아래의 그림을 확인해보자.

bugfix 브랜치가 master의 D커밋 base로 재배치하는 상황.

bugfix라는 브랜치가 있고 master라는 브랜치가 있다고 할때, bugfix라는 브랜치가 master브랜치에 rebase를 진행했다고 표현할 수 있다. 이 방법은, merge와 같이 병합을 할 수 있는 또다른 방법이다. 그림처럼 rebase가 진행이 되면, master브랜치는 X, Y라는 커밋이 반영되고 HEAD를 master의 Y커밋으로 이동시킨다.

 

[command]

$ git rebase [브랜치명]

: 기준 브랜치를 대상브랜치의 베이스를 가지고 rebase를 진행한다. (위의 그림과 같은 상황에서는 git checkout bugfix / git rebase master 명령어가 수행되었다)

 

(!) rebase시 주의사항

rebase는 history관리에 유리하고 커밋내용을 자유자재로 만들어 낼 수 있는 등의 장점이 있지만, 동시에 주의해야할 부분들이 있다.

rebase는 merge와는 다르게 커밋을 새로 작성하는 원리이다. 그래서 리베이스를 할 때마다 고유 hash값이 변경된다. (그림에서 X를 X'라고 표현한 이유) rebase이후 push를 하게되면 다른 개발자는 완전히 변경된 내용으로 보이게 된다. 만약 다른 개발자가 작업했던 내용을 pull받지 않고 rebase이후 강제로 push를 진행시, commit이 유실될 위험이 있다.. 큰일난다. 따라서 rebase할 브랜치가 다른 개발자들과 공유하고 있을 경우에는, 반드시 사전에 공지하고 최신 코드를 반영한 상태에서 rebase를 진행해야 할 것이다.

'Git' 카테고리의 다른 글

Git - SVN과의 비교  (0) 2022.03.10
Git - Branching Model  (0) 2021.02.25
Git - 동작 정리 (심화편)  (0) 2021.02.17