Git squash

3 분 소요

squash

다수의 커밋을 하나로 만들기

squash 옵션은 여러 개의 커밋을 하나의 커밋 이력으로 묶어주는 역할을 수행합니다.

우선 엄밀히 말하여 git squash라는 명령어는 존재하지 않으며,

squash는 git rebase -i (interactive rebase)명령어에서 제공하는 옵션을 의미합니다.

다음과 같이 login이라는 작업에 대해 3개의 커밋이 별도로 존재할 때

squash는 이것을 하나의 커밋 이력으로 만들어주는 역할을 합니다.

$ git log --oneline
b142b67 (HEAD -> feature/sample_logic) login function 1-3
86e7823 login function 1-2
bf3b110 login function 1-1
e6eb535 (origin/master, origin/develop, origin/HEAD, develop) init commit

현재 커밋 로그를 그래프로 나타내면 다음과 같습니다.

graph LR;
  A["e6eb535 (init commit)"] -->B["bf3b110 (login function 1-1)"];
  B["bf3b110 (login function 1-1)"] -->C["86e7823 (login function 1-2)"];
  C["86e7823 (login function 1-2)"] -->D["b142b67 (login function 1-3)"];

squash를 이용하여 3개의 커밋을 하나의 새로운 커밋으로 만들 것이며, 이 과정을 마치고 나면 최종적으로 하나의 커밋 이력만 나타나게 됩니다.

graph LR;
  A["e6eb535 (init commit)"] -->B["commit_hash (login function (3/3))"];

squash 적용해보기

local repository의 HEAD가 가리키는 부분(login function 1-3)을 포함하여 이전의 3개의 커밋에 대해 rebase를 수행할 것입니다.

$ git rebase -i HEAD~3

위 명령어를 입력하면 아래와 같은 화면이 나타납니다.

pick bf3b110 login function 1-1
pick 86e7823 login function 1-2
pick b142b67 login function 1-3

# Rebase e6eb535..b142b67 onto e6eb535 (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.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

squash를 수행하기 위해 pick 태그를 s 또는 squash로 변경하고 저장 후 나가기(:wq)를 수행합니다.

pick bf3b110 login function 1-1
squash 86e7823 login function 1-2
squash b142b67 login function 1-3
...

새로운 vi 화면이 나타나게 되고 커밋 메시지를 수정할 수 있습니다.

# This is a combination of 3 commits.
# This is the 1st commit message:

login function (3/3)

# This is the commit message #2:

login function 1-2

# This is the commit message #3:

login function 1-3

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date:      Sun Aug 2 16:33:15 2020 +0900
#
# interactive rebase in progress; onto e6eb535
# Last commands done (3 commands done):
#    squash 86e7823 login function 1-2
#    squash b142b67 login function 1-3
# No commands remaining.
# You are currently rebasing branch 'feature/sample_logic' on 'e6eb535'.
#
# Changes to be committed:
#       new file:   login.cpp
#

커밋 메시지 수정하고 저장 후 나가기(:wq)를 수행하면 rebase가 수행되었다는 메시지가 출력됩니다.

$ git rebase -i HEAD~3
[detached HEAD e22cf33] login function (3/3)
 Date: Sun Aug 2 16:33:15 2020 +0900
 1 file changed, 4 insertions(+)
 create mode 100644 login.cpp
Successfully rebased and updated refs/heads/feature/sample_logic.

git log 명령어를 통해 확인하면 하나의 커밋으로 만들어진 것을 확인할 수 있습니다.

$ git log --oneline
e22cf33 (HEAD -> feature/sample_logic) login function (3/3)
e6eb535 (origin/master, origin/develop, origin/HEAD, develop) init commit
graph LR;
  A["e6eb535 (init commit)"] -->B["e22cf33 (login function (3/3))"];

카테고리:

업데이트: