본문 바로가기

Dot ./개인 공부 기록용

GIT 사용할 때 협업시 미리 알고 있으면 좋은 명령어

    Git 초보자 입장으로 개발하면서 실제로 자주 사용하는 Git 명령어들을 모아봤다. 실제로 커밋을 되돌리거나 합치는 경우 그리고 실수로 커밋을 누른 경우 등 내가 겪었던 내용들과 어떻게 해결했는지 정리해봤다. 추가로 Dangit, Git?! 을 보며 많은 도움을 얻었다.

     

    일단 local에서 remote으로 push를 한 경우 커밋 내역을 변경하는 것은 내가 알기로는 거의 불가능하다.(git push --force를 통해 하는 방법은 있지만 이는 다른 팀원들의 local 기록으로 수동으로 수정해줘야 하기 때문에 사용되지 않는다) 그래서 revert 명령어로 롤백을 하거나 수정한 커밋을 치는 방법밖에 없다. 그러니 항상 remote로 push를 할 때는 신중히하자.

     

     

    GIT Local/ Remote

    GIT 명령어를 알기 전에 간략하게 GIT이 어떠한 구조를 지니고 있는 지 알아보자.

     

    GIT Local, Remote 영역

    Working Directory

    현재 작업하고 있는 영역으로 untracked/ tracked로 구분된다.

    • untracked: git에 아직 추가되지 않은 새로운 파일
    • tracked: git에 추가된 tracking이 가능한 파일

     

    tracked는 수정 여부에 따라 unmodified/ modified로 나뉜다.

    • unmodified: 수정된 내용이 없는 상태
    • modified: 수정된 내용이 있는 상태. 해당 상태를 가진 파일만 staging area으로 옮길 수 있음

     

    Staging Area

    commit 할 준비가 되어 있는 파일들을 옮겨두는 영역이다. 보통 staging 영역에 옮기기 위해 git add . 명령어를 많이 사용한다.

     

    Local Repository

    Local 영역에서 버전 히스토리를 저장하는 영역이다.

     

    Remote Repository

    Remote 서버에서 버전 히스토리를 관리하는 영역이다. Loca 버전 관리 유실을 대비하고 다른 사람과 같은 디렉토리를 공유하며 협업을 하기 위해 사용하는 영역이다.

     

    1. 여러 작업을 하다보니 로컬 Git 저장소를 한 눈에 정리하고 싶을 때

    이는 아차할 정도는 아니지만 그냥 현재 이용한 git 히스토리를 한 눈에 보기 좋은 명령어다. 사실 source tree와 같은 GUI 툴을 사용해도 한 눈에 쉽게 현재 위치를 파악할 수 있다.

     

    git reflog 

    브런치와 HEAD 번호, commit hash에 대한 정보가 나와있기 때문에 해당 정보를 통해 어디서 어떤 일이 벌어졌는지 쉽게 파악할 수 있다. 그래서 나는 돌아가고 싶은 브런치나 커밋 위치가 있다면 해당 명령어를 자주 사용한다.

    123da8f6 (HEAD -> branch_a, origin/branch_a) HEAD@{0}: commit: message4
    0e4449a0 HEAD@{1}: commit: message3
    142fxbb3 HEAD@{2}: commit: message2
    9279ze70 HEAD@{3}: commit: message1
    44374fda (origin/develop, develop) HEAD@{4}: checkout: moving from develop to branch_a

     

    2. 방금 커밋 했는데 깜빡한 내용을 추가로 넣고 싶을 때

    수정 내용을 최신 커밋에 바로 넣는 경우

    다음 두 명령어를 입력하면 최신 커밋에 따로 수정없이 add된 파일들이 합쳐진다

     

    git add .

    git commit --amend --no-edit

     

    커밋 내역은 그대로이지만 이 또한 reflog로 보면 다음과 같이 구분되어있는 것을 볼 수 있다. 

    x233fbb3 HEAD@{0}: commit (amend): docs reamde update
    8199ee24 HEAD@{1}: commit: docs reamde update

     

    3. 이미 커밋한 내용들을 최신 커밋과 합치고 싶을 때

    여러 커밋과 합치고 싶다면 rebase에 있는 squash merge를 하는 방법을 사용하면 된다. rebase 명령어는 branch의 base를 다시 설정하는 명령어이다. 

    git rebase -i HEAD~3

    현재 커밋 위치에서 보고싶은 커밋 수 만큼 HEAD~ 뒤에 숫자를 입력해주면 된다. 그렇게 에디터가 켜지고 주석으로 친절하게 각 기능들을 잘 설명주고있다. 커밋 메세지 합치기는 s(squash)이므로, pick을 squash로 수정해주고 :wq를 누른 후 다음 에디터 화면에서 합쳐지는 커밋 메세지들은 모두 주석 처리해주면 된다

    pick 1933xxb3 commit message1
    pick 0q5212z0 commit message2 
    pick cxq2f99c commit message3
    
    # Rebase 36374fda..c3a1f67c onto 36374fda (3 commands)
    #
    # Commands:
    # p, pick <commit> = use commit
    # r, reword <commit> = use commit, but edit the commit message
    # e, edit <commit> = use commit, but stop for amending
    # s, squash <commit> = use commit, but meld into previous commit
    # f, fixup <commit> = like "squash", but discard this commit's log message
    # x, exec <command> = run command (the rest of the line) using shell
    # b, break = stop here (continue rebase later with 'git rebase --continue')
    # d, drop <commit> = remove commit
    # l, label <label> = label current HEAD with a name
    # t, reset <label> = reset HEAD to a label
    # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
    # .       create a merge commit using the original merge commit's
    # .       message (or the oneline, if no original merge commit was
    # .       specified). Use -c <commit> to reword the commit message.
    
    
    
    ### 변경 후
    pick 1933xxb3 commit message1
    s 0q5212z0 commit message2 
    s cxq2f99c commit message3

     

    4. 이미 커밋한 메세지를 수정하고 싶을 때

    최신 커밋을 수정하는 경우

    텍스트 에디터가 켜지면서 커밋 메세지를 수정할 수 있다. 오타나 막상 적고나니 마음에 들지 않을 때 사용하기 좋다. 

    git commit --amend 

    your commit message
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    # 
    # ...

     

    또는 -m 을 붙여서 에디터 접속없이 바로 수정할 수도 있다.

    git commit --amend  -m "커밋 메세지 수정"

     

    최신보다 더 오래된 커밋을 수정하는 경우

    그런데 위 명령어는 가장 최신 커밋만 수정이 가능하다. 만약 최신 커밋이 아닌 이전 커밋의 내역을 수정하고 싶다면 rebase를 사용하자. 

     

    git rebase -i HEAD~3

    rebase 명령어를 입력해보면 다음과 같이 에디터가 켜진다. 커밋 메세지 수정은 r(reword)이므로, pick을 reword로 수정해주고 :wq를 누른 후 다음 에디터 화면에서 커밋 메세지를 잘 수정해주면 된다

    pick 1933xxb3 commit message1
    pick 0q5212z0 commit message2 
    pick cxq2f99c commit message3
    
    # Rebase 36374fda..c3a1f67c onto 36374fda (3 commands)
    #
    # Commands:
    # p, pick <commit> = use commit
    # r, reword <commit> = use commit, but edit the commit message
    # e, edit <commit> = use commit, but stop for amending
    # s, squash <commit> = use commit, but meld into previous commit
    # f, fixup <commit> = like "squash", but discard this commit's log message
    # x, exec <command> = run command (the rest of the line) using shell
    # b, break = stop here (continue rebase later with 'git rebase --continue')
    # d, drop <commit> = remove commit
    # l, label <label> = label current HEAD with a name
    # t, reset <label> = reset HEAD to a label
    # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
    # .       create a merge commit using the original merge commit's
    # .       message (or the oneline, if no original merge commit was
    # .       specified). Use -c <commit> to reword the commit message.
    
    
    
    ### 변경 후
    pick 1933xxb3 commit message1
    r 0q5212z0 commit message2 
    r cxq2f99c commit message3

     

    5. 실수로 master 또는 develop 브런치에 커밋해서 되돌리고 싶을 때 (local)

    당황하지 말고 현재 상태에서 새로운 branch를 따고 현재 커밋된 내역을 되돌리면 된다. 참고로 local의 경우에만 한정된다. 만약 remote 저장소로 push를 했다면 얼른 롤백하자.

     

    가장 최신 커밋만 되돌리는 경우

    1. reset --hard

    git branch new-branch-name  # 현재 커밋 상태 그대로 새로운 브런치 생성

    git reset HEAD~ --hard  # 현재 브런치에서는 해당 커밋 되돌려 버리기

    git checkout new-branch-name  # 새로운 브런치로 이동

     

    2. reset --soft

    또는 --soft로 되돌린 후 변경된 내역을 다시 한 번 확인한 다음 커밋하는 방법도 있다

    git reset HEAD~ --soft

    git stash  # 되돌린 내역 stash 영역에 저장

    git checkout new-branch-name  # new-branch-name 브런치로 이동

    git stash pop # 가장 최근에 stash  영역에 저장한 코드 꺼내기

    git add .

    git commit -m "new commit message"

     

    3.  cherry-pick

    또는 cherry-pick을 사용해볼 수 도 있다. 가져오고 싶은 브런치의 커밋을 선택한 후 해당 브런치로 가서 커밋을 삭제한다.

    git checkout new-branch-name

    git cherry-pick master # master의 가장 최신 커밋을 선택

    git checkout master

    git reset HEAD~ --hard 

     

    여러 커밋을 되돌리고 싶을 경우

    처음에 배웠던 reflog 명령어를 이용하여 모든 기록을 보고 이동하고 싶은 HEAD@{index}를 찾아 이동한다.

    git reflog  # 모든 기록 보기

    git reset HEAD@{index} # 해당 커밋으로 이동한다.

     

    6. 잘못 구현한 코드를 이미 여러 번 커밋을 해서 다시 예전으로 되돌리고 싶을 때 

    실수를 바로 알아차릴 수 있으면 실수가 아니다. 실수를 늦게 알아차렸을 때 해당 커밋을 되돌리고 싶을 때는 git log로 해당 커밋을 찾은 후 reset HEAD 뒤에 원하는 커밋 수만큼 입력해주면 된다.

    git log # 해당 커밋을 찾는다

    git reset HEAD~{되돌리고 싶은 커밋 수} # 해당 커밋을 찾는다

     

    7. 묵혀둔 로컬 브랜치를 한번에 삭제하고 싶을 때

    grep으로 찾은 브런치를 xargs 명령에 pipeline으로 넘겨줘서 삭제한다

     git branch | grep feature | xargs git branch -D

    Deleted branch feature/123 (was 11z7dc46).
    Deleted branch feature/124 (was 937122ab).
    Deleted branch feature/125 (was a27cf35f).
    Deleted branch feature/126 (was e34bv940).
    Deleted branch feature/127 (was 487bb484).