Merge Conflict 후 커밋 무한 대기
feat 브랜치를 develop 기준으로 병합하면서 충돌을 해결하고 커밋까지 했는데, 커밋이 진행되지 않고 끝나지 않았다. 😱
오늘 feat 브랜치를 develop 기준으로 최신화하려고 merge했는데, 충돌 해결 후 커밋이 멈춰버린 문제를 겪었다. 이를 해결하며 정리한 내용을 공유한다.
CLI로도 시도해보고, GitHub Desktop에서 “continue merge”를 눌러도 계속 로딩 상태였다.

IntelliJ에서 롤백을 하면 Unversioned Files 상태로 빠져서 다시 `git add`가 필요했는데, GitHub Desktop에서는 변경 파일 전체를 선택해서 “Discard all changes” 하니까 자동으로 `merge` 커밋이 생성되어 바로 푸시할 수 있었다.

IntelliJ vs GitHub Desktop에서 커밋/푸시/롤백/디스카드의 차이점
1. 공통 개념 (기본)
- git add : staging area에 추가
- git commit : staging area → 커밋 히스토리
- git push : local 커밋 → remote 저장소
- reset / discard / rollback : unstaged 변경, staged 변경, 커밋 자체까지 되돌리는 수준을 다룸
2. IntelliJ의 Rollback / Discard
IntelliJ IDEA에서 “Rollback” (혹은 “Discard”) 버튼
- 현재 워킹 디렉토리에서 변경된 파일의 수정사항을 되돌려버림
- 변경 → Unversioned 상태로 가는 경우:
- Git이 추적 중이던 파일: 수정 사항이 사라지고 → HEAD 커밋 상태로 돌아감
- 새 파일 (untracked): Git이 모르는 파일 → 버전 관리에서 사라지고 → 로컬엔 그대로 있음 (Unversioned Changes로 보임)
- 새 파일은 git add를 다시 해줘야 함
예시
TrackedFile.ts (수정됨) -> Rollback -> HEAD 상태로 돌아감
UntrackedFile.ts -> Rollback -> Unversioned Changes로 이동
3. GitHub Desktop 의 Discard Changes
GitHub Desktop의 “Discard Changes” 버튼
- “Discard”는 Git reset –hard 와 거의 동일하게 동작
- Untracked (새로 생성된) 파일은 완전히 삭제
- → IDEA처럼 Unversioned Changes로 남지 않음
- Git이 추적 중인 파일의 변경 사항은 HEAD로 되돌림
차이
- Desktop에서는 새 파일을 깔끔하게 지워버려서 깨끗해짐
- IDEA에서는 새 파일은 그대로 → unversioned changes로 보여서 헷갈릴 수 있음
4. Merge Commit 이 자동 생성된 이유
GitHub Desktop에서 “Discard” 후에도 Merge Commit이 남아있던 이유
- IDEA나 CLI에서 `merge` 실행
- 이미 `merge`를 실행했으면 .git/MERGE_HEAD 가 남아있음
- 충돌 해결 전에는 “`merge` 상태” 유지
- IDEA에서 롤백: 충돌난 파일 내용만 되돌림 (MERGE_HEAD 유지될 수 있음)
- GitHub Desktop에서 Discard All:
- 변경 파일을 되돌림 + merge 상태 종료 시도 → 자동으로 merge commit 생성
- “Merge 브랜치 into 브랜치” 커밋이 자동으로 만들어짐
`merge` 상태에서 conflict 해제나 Discard All 하면 merge 커밋이 자동 생성됨
5. 커밋/푸시 차이
IDEA
- Add → Commit → Push 명령어가 단계적으로 명확
- unversioned → git add 필요
- 커밋 메시지 편집, amend, partial stage 가능
GitHub Desktop
- stage 영역이 암시적
- “Commit to 브랜치” 버튼으로 staged/unstaged가 추상화됨
- Untracked 파일까지 깔끔히 Discard
- conflict 해결 → merge commit 자동 생성 흐름이 더 단순화
6. 정리
- IntelliJ: granularity 좋음 (파일별 add, hunk별 add, 스테이징 세밀)
- Github Desktop: 직관적이지만 스테이징 상태 관리가 상대적으로 덜 투명
- 충돌 해결 시 Github Desktop은 자동 merge commit 만들 가능성 높음
- CLI나 IntelliJ에서는 수동으로 commit 메시지 편집 가능
결론
✔️ IDEA의 Rollback
- untracked 파일 → unversioned changes로 보관
- tracked 파일 → HEAD로 되돌림
✔️ GitHub Desktop의 Discard
- untracked 파일 → 삭제
- tracked 파일 → HEAD로 되돌림
- `merge` 상태 → 자동 merge commit 생성
만약 “`merge` 충돌 해결 시 불필요한 자동 `merge` 커밋이 생성되는 걸 피하고 싶다” 면:
git merge --no-commit
- 위 옵션을 사용하면 `merge` 상태로만 유지되고 자동 커밋이 생성되지 않음
- 충돌을 직접 해결한 뒤, 원하는 파일을 git add로 스테이징
- 마지막에 내가 원하는 메시지로 커밋 가능
예시
git merge --no-commit origin/develop
# (충돌 해결)
git add .
git commit -m "feat: resolve merge conflicts with clean history"
이렇게 하면 `merge` 히스토리를 더 깔끔하게 관리할 수 있다.
후기
저때 `git commit` 시 `pre-commit` 훅에 설정된 `lint-staged`가 무한정 실행되었던 원인은, 최초 브랜치 생성 시 `origin/`을 명시하지 않아 발생한 문제로 보인다.
문제 발생 메커니즘:
1. 브랜치 생성 방식의 차이:
- `git checkout -b <새_브랜치_이름> origin/<원격_브랜치_이름>` : 원격 브랜치(origin/develop)의 최신 상태를 기준으로 새 로컬 브랜치를 생성하고 추적 설정까지 자동으로 해준다.
- `git checkout <기존_로컬_브랜치> 후 git checkout -b <새_브랜치_이름>` : 현재 로컬 HEAD(즉, 로컬 develop의 최신 커밋)가 가리키는 커밋을 기준으로 새 로컬 브랜치를 생성한다.
새 로컬 브랜치를 원격 브랜치와 동일하게 시작하고 싶다면 origin/을 명시하는 것이 가장 정확하고 일반적인 방법이다.
2. A 개발자의 브랜치 생성:
- 다른 A 개발자가 인텔리제이에서 'Create Branch' 기능을 사용하여 새 브랜치를 생성했을 때, `origin/develop`이 아닌 A 개발자의 로컬 develop 브랜치의 최신 커밋을 기반으로 새 브랜치가 만들어진 것으로 추정된다.
- 만약 A 개발자의 로컬 develop이 git pull 등으로 origin/develop과 동기화되지 않은 상태였다면, 새로 생성된 브랜치는 원격 develop에는 이미 적용된 lint-staged 관련 수정사항(코드 포맷팅, 스타일 등)이 누락된 채로 시작하게 된다.


3. lint-staged의 무한 실행:
- 이렇게 생성된 브랜치에서 `git commit`을 시도하면, `pre-commit` 훅에 설정된 `lint-staged`가 실행된다.
- lint-staged는 스테이징된 파일들을 검사하면서, 누락되었던 코드 스타일/포맷팅 오류들을 발견하고 `eslint --fix` 등으로 자동으로 수정하려고 시도한다.
- 하지만 이 수정 과정이 한 번에 완벽하게 완료되지 않거나, 수정된 파일이 다시 스테이징되는 과정에서 Git 커밋 프로세스와의 동기화 문제 등으로 인해 `pre-commit` 훅이 끝없이 반복되거나 실패하여 커밋이 진행되지 못한다.
해결
lint-staged의 실행이 끝나지않는다고하여, 해당 실행 옵션을 무시하고 커밋할 순 없었기 때문에 결국 `origin/develop`을 기준으로 새 브랜치를 생성하고 기존 작업 내용을 머지함으로써, `pre-commit` 문제를 해결하였다.
'Development' 카테고리의 다른 글
| [Cursor] Figma MCP 연결하기 (더이상의 반복 작업은 지양한다) (2) | 2025.09.30 |
|---|---|
| [ChatGPT] 이미 구독 중이라면, 3개월 동안 Plus 50% 할인 받기 (0) | 2025.09.29 |
| [IntelliJ] JIRA Integration 사용 (0) | 2025.06.12 |
| [VSCode] VScode 기본 기능에 대해 알아보자 (0) | 2025.06.11 |
| [Cursor] Cursor 셋팅하기 (0) | 2025.06.09 |