#git 왜 merge 실수로 희생된 커밋이 파일 로그에서 보이지 않나?

2 minute read

“커밋이 사라졌어요”

“push는 했나요?” “네” 그럼 커밋이 사라질 리는 없다. git database에 저장하는 객체는 변하지 않는다(immutable). 그런데 왜 찾질 못하는 걸까? 파일 history를 봐도 사라진 커밋이 안 보인다.

커밋이 사라진 건 아니었다. merge 실수 때문이었다. 충돌(conflict)이 났는데, master로 엎어 써버렸다. 실수할 수도 있지. 이건 넘어간다고 하더라도 왜 파일 history에 merge 실수를 한 커밋도 안 보이는 건가?

Default mode: Simplifies the history to the simplest history explaining the final state of the tree. Simplest because it prunes some side branches if the end result is the same (i.e. merging branches with the same content) - git-log default mode

History Simplification 때문이다. 디폴트 모드에서는 도중에 어떤 변경을 했든 간에 끝이 같은 브랜치는 가지치기(prune)를 한다. 즉, master 브랜치 내용으로 엎어 써버렸다면 끝이 같기 때문에 브랜치에서 변경한 커밋이 파일 history에서 안 보였다.

이런 경우 --full-history 혹은 --simplify-merges 옵션을 사용하면 된다.

간단한 예를 만들어봤다.

$ git log --graph --oneline --decorate
* 4e758f6 (HEAD -> master) add test2
*   b353c23 Merge branch 'dev'
|\
| * 8d8076d (dev) line 3
| * 9380232 line 1~2
* | a05f33e line one 1, line two 2, line three 3
|/
* 3ca309d line one~three

dev 브랜치를 master에 머지했다.

$ git diff 8d8076d b353c23
diff --git a/test b/test
index a92d664..6d86227 100644
--- a/test
+++ b/test
@@ -1,3 +1,6 @@
-line 1
-line 2
-line 3
+line one
+line two
+line two
+line three
+line three
+line three

$ git diff a05f33e b353c23

b353c23 머지 커밋에서 dev 브랜치 변경 사항이 무시됐다. 머지할 때, 충돌(conflict)이 났다. dev 브랜치 변경 사항을 무시하고 master 내용으로 머지했다.

$ git log --oneline test
a05f33e line one 1, line two 2, line three 3
3ca309d line one~three

파일 로그를 보면 dev 브랜치 로그가 안 나온다.

$ git log --oneline --graph --full-history test
*   b353c23 Merge branch 'dev'
|\
| * 8d8076d line 3
| * 9380232 line 1~2
* | a05f33e line one 1, line two 2, line three 3
|/
* 3ca309d line one~three

--full-history 옵션을 붙이면 된다. test 파일 로그를 조회했기 때문에 test2 파일을 추가한 4e758f6 커밋은 안 나온다.

$ git log --oneline --graph --simplify-merges test
*   b353c23 Merge branch 'dev'
|\
| * 8d8076d line 3
| * 9380232 line 1~2
* | a05f33e line one 1, line two 2, line three 3
|/
* 3ca309d line one~three

--full-history 결과에서 의미 없는 머지 커밋을 걸러낸 결과만 보여주는 --simplify-merges 옵션을 사용해도 된다. 이 옵션을 추천. 간단한 예제라 로그 내용이 같다. rebase 안 하는 저장소에서 --full-history 옵션으로 로그를 보는 것만큼 무모한 행동은 없다.

$ git log --oneline --graph --simplify-by-decoration test
* 4e758f6 add test2
*   b353c23 Merge branch 'dev'
|\
| * 8d8076d line 3
| * 9380232 line 1~2
* | a05f33e line one 1, line two 2, line three 3
|/
* 3ca309d line one~three

--simplify-by-decoration 옵션을 사용해도 나온다. tag나 branch가 가리키는 커밋 위주로 히스토리를 보여주는 옵션인데, 이걸 file 로그에 사용해도 원하는 전체 그림은 볼 수 있다. 다만 test와 상관없는 test2 파일을 추가한 4e758f6 커밋도 같이 나온다. 이 옵션으로 merge를 잘못한 커밋을 찾아냈다. 지금 생각해보면 뒷걸음질 치다가 쥐를 잡은 것 같기도 하고.

참고