[Git] Git Merge 충돌, IntelliJ와 GitHub Desktop에서 다르게 동작하는 이유

2025. 6. 27. 16:13·Development

Merge Conflict 후 커밋 무한 대기

feat 브랜치를 develop 기준으로 병합하면서 충돌을 해결하고 커밋까지 했는데, 커밋이 진행되지 않고 끝나지 않았다. 😱

오늘 feat 브랜치를 develop 기준으로 최신화하려고 merge했는데, 충돌 해결 후 커밋이 멈춰버린 문제를 겪었다. 이를 해결하며 정리한 내용을 공유한다.

 

CLI로도 시도해보고, GitHub Desktop에서 “continue merge”를 눌러도 계속 로딩 상태였다.

Github Desktop

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

cli

 


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 관련 수정사항(코드 포맷팅, 스타일 등)이 누락된 채로 시작하게 된다.

[IntelliJ] Local의 develop 브랜치
[IntelliJ] Create Branch


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
'Development' 카테고리의 다른 글
  • [Cursor] Figma MCP 연결하기 (더이상의 반복 작업은 지양한다)
  • [ChatGPT] 이미 구독 중이라면, 3개월 동안 Plus 50% 할인 받기
  • [IntelliJ] JIRA Integration 사용
  • [VSCode] VScode 기본 기능에 대해 알아보자
곽진돔
곽진돔
Developer
  • 곽진돔
    echo "곽박한 세상";
    곽진돔
  • 전체
    오늘
    어제
    • 분류 전체보기 (201)
      • Development (68)
        • Linux (13)
        • k8s (3)
        • Docker (5)
        • AWS (1)
        • PHP (35)
        • Python (21)
        • Java (1)
        • SpringBoot (4)
        • JavaScript (1)
        • React (10)
        • MySql (19)
        • MongoDB (1)
      • Daily (5)
      • Study (7)
        • TIL (2)
        • license (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
    • 글쓰기
    • 설정
  • 링크

    • github
  • 공지사항

  • 인기 글

  • 태그

    ssh
    크롤링
    인코딩
    error
    docker
    db
    JavaScript
    Linux
    Shell
    HTML
    nodejs
    정규표현식
    CentOS7
    Java
    IP
    Python
    chromedriver
    SQL
    CentOS
    윈도우
    Selenium
    date
    UTF8
    리액트
    php
    스프링부트
    리눅스
    springboot
    MySQL
    react
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
곽진돔
[Git] Git Merge 충돌, IntelliJ와 GitHub Desktop에서 다르게 동작하는 이유
상단으로

티스토리툴바