Visual Git 마스터하기: Tig를 활용한 인터랙티브 Git 강좌
모듈 1: 첫걸음 - Git과 Tig, 그리고 첫 만남
강좌 목표: Git과 Tig의 필요성을 이해하고, 직접 설치하여 첫 커밋 히스토리를 tig
로 확인하는 경험을 합니다. '명령어의 결과'를 '시각적인 히스토리'로 인식하는 첫 단추를 끼웁니다.
1. Intro: 왜 Git을 써야 할까? (버전 관리의 필요성)
혹시 이런 경험 없으신가요?
최종_보고서.docx
, 진짜_최종_보고서.docx
, 이게진짜최종_보고서_수정1.docx
...
프로젝트 파일이 복잡해질수록 우리는 파일명에 의존해 버전을 관리하곤 합니다. 하지만 이건 매우 위험하고 비효율적인 방법입니다. 만약 동료와 함께 이 파일을 수정한다면요? 누가 어떤 부분을 수정했는지, 실수로 중요한 내용을 삭제했다면 어떻게 되돌릴 수 있을까요?
Git은 바로 이 문제를 해결하는 '버전 관리 시스템(Version Control System)'입니다. Git을 사용하면 다음과 같은 강력한 능력을 얻게 됩니다.
-
시간 여행 (코드의 스냅샷 저장): 프로젝트의 특정 상태를 '커밋(Commit)'이라는 단위로 저장합니다. 마치 게임의 '세이브 포인트'처럼, 언제든 원하는 시점의 코드로 돌아갈 수 있습니다. 버그가 발생했을 때, 어떤 변경사항 때문에 문제가 생겼는지 쉽게 추적하고 되돌릴 수 있죠.
-
안전한 협업 (독립적인 작업 공간): '브랜치(Branch)'라는 기능을 통해 기존 코드를 건드리지 않고, 자신만의 독립적인 공간에서 새로운 기능을 개발하거나 버그를 수정할 수 있습니다. 작업이 완료되면 원래의 코드와 안전하게 합칠 수 있어 여러 명이 동시에 작업해도 코드가 꼬이지 않습니다.
-
든든한 백업 (히스토리 전체 보관): 단순 파일 백업과 다릅니다. Git은 프로젝트의 '모든 변경 이력'을 저장합니다. 내 컴퓨터의 파일이 모두 사라져도, GitHub 같은 원격 저장소에 올려두었다면 모든 히스토리와 함께 프로젝트 전체를 완벽하게 복원할 수 있습니다.
결론: Git은 더 이상 선택이 아닌, 현대 개발자에게 꼭 필요한 기본 소양입니다.
2. Intro: Tig는 무엇이고 왜 써야 할까? (Git의 시각화)
Git은 정말 강력하지만, 모든 상호작용이 터미널의 텍스트 명령어로 이루어집니다. 예를 들어, 프로젝트의 변경 이력을 보려면 git log
명령어를 사용합니다.
# git log --oneline --graph --all 의 출력 예시
* 1ab2c3d (HEAD -> feature/login) Add login button
* 4d5e6f7 Implement login logic
| * 8g9h0i1 (main) Fix typo in README
|/
* 7j8k9l0 Initial commit
이것도 유용하지만, 브랜치가 수십 개로 복잡해지면 텍스트만으로는 전체 구조를 파악하기 매우 어렵습니다.
그래서 우리는 대안을 찾습니다.
- GUI 툴 (SourceTree, GitKraken 등): 예쁜 그래픽으로 히스토리를 보여줘서 직관적이지만, 프로그램이 무겁고, 마우스를 써야 하며, 터미널 환경을 벗어나야 하는 단점이 있습니다.
- Tig (Text-mode Interface for Git): 바로 이 지점에서
tig
가 빛을 발합니다.tig
는 터미널 환경을 벗어나지 않으면서도 Git 히스토리를 그래픽 유저 인터페이스(GUI)처럼 시각적으로 보여주는 놀라운 도구입니다.
Tig를 써야 하는 이유:
- 가볍고 빠릅니다: 터미널에서 즉시 실행됩니다.
- 시각적입니다: 복잡한 브랜치 구조와 커밋 히스토리를 ASCII 아트로 그려주어 한눈에 파악할 수 있습니다.
- 인터랙티브합니다: 단순히 보기만 하는 게 아니라,
tig
화면 안에서 커밋 내용을 자세히 보고, 브랜치를 바꾸고, 심지어 커밋까지 할 수 있습니다.
결론:
tig
는 CLI(Command Line Interface)의 속도와 효율성 + GUI의 시각적 직관성을 모두 잡은, Git 경험을 10배 향상시키는 최고의 파트너입니다.
3. 설치 및 기본 설정
tig
는 Git의 '뷰어'이므로, 당연히 Git이 먼저 설치되어 있어야 합니다.
1) Git 설치
대부분의 최신 운영체제에는 Git이 이미 설치되어 있습니다. 터미널을 열고 확인해보세요.
git --version
만약 설치되어 있지 않다면 공식 사이트를 참고하여 설치해주세요.
2) Tig 설치
각 운영체제에 맞는 패키지 매니저를 사용하면 간단히 설치할 수 있습니다.
-
macOS (Homebrew 사용):
brew install tig
-
Ubuntu/Debian Linux (apt 사용):
sudo apt-get update sudo apt-get install tig
-
Windows (scoop 또는 winget 사용): Git for Windows (Git Bash) 환경에서 사용하는 것을 권장합니다.
# scoop 사용 시 scoop install tig # winget 사용 시 winget install tig
3) 최초 Git 설정
Git을 처음 설치했다면, 커밋에 기록될 사용자 정보(이름, 이메일)를 설정해야 합니다. 이 정보는 당신의 '디지털 서명'과 같습니다.
git config --global user.name "Your Name"
git config --global user.email "youremail@example.com"
4. 나의 첫 번째 저장소와 첫 Tig 실행 (실습)
이제 Git과 tig
를 직접 경험해볼 시간입니다.
1. 실습용 폴더를 만들고 이동합니다.
mkdir my-git-project
cd my-git-project
2. 이 폴더를 Git 저장소로 초기화합니다.
이 명령을 실행하면 폴더 내에 숨김 파일인 .git
디렉토리가 생성되며, 이제 Git이 이 폴더의 모든 변경사항을 추적하기 시작합니다.
git init
3. 첫 번째 파일을 만들고, Git에게 추적하라고 알려줍니다 (add
).
add
는 변경된 파일들을 '스테이징 영역(Staging Area)'이라는 커밋 대기실로 보내는 과정입니다.
echo "Hello, Git World!" > README.md
git add README.md
4. 첫 번째 커밋(스냅샷)을 남깁니다.
commit
은 스테이징 영역에 있는 파일들을 하나의 의미 있는 변경사항 묶음(스냅샷)으로 저장하고, 메시지를 남기는 행위입니다.
git commit -m "Initial commit: Add README.md"
5. 대망의 순간: tig
를 실행합니다!
이제 터미널에 tig
라고만 입력하고 Enter를 누르세요.
tig
축하합니다! 다음과 비슷한 화면을 보게 될 것입니다.
[main] [HEAD] o 2023-10-27 Your Name Initial commit: Add README.md
--
main:
(0) Main view
(s) Status (l) Log (d) Diff (t) Tree
(f) File log (b) Blame (r) Refs (y) Stash
(h) Help (q) Quit
tig
화면 분석:
[main] [HEAD] o ...
: 이것이 방금 우리가 만든 커밋입니다.[main]
: 현재main
브랜치에 있다는 뜻입니다.[HEAD]
: 현재 작업 중인 위치(포인터)를 의미합니다.o
: 커밋을 나타내는 점입니다.- 뒤이어 날짜, 작성자(
git config
에서 설정한 이름), 그리고 커밋 메시지가 보입니다.
기본 조작법:
k
또는 위쪽 화살표: 위로 이동j
또는 아래쪽 화살표: 아래로 이동Enter
: 선택한 커밋의 변경 내용(Diff) 보기q
:tig
종료하기 (또는 이전 화면으로 돌아가기)
미션:
-
파일을 한 번 더 수정하고, 두 번째 커밋을 만들어보세요.
echo "Learning tig is fun!" >> README.md git add README.md git commit -m "Update README with tig info"
-
다시
tig
를 실행해서 커밋이 두 줄로 쌓인 히스토리를 눈으로 직접 확인해보세요. -
키보드
j
,k
로 커밋 사이를 오가보고, 각 커밋에서Enter
를 눌러 어떤 내용이 변경되었는지 확인해보세요.
모듈 1 요약:
당신은 이제 Git이 왜 필요한지 설명할 수 있고, tig
를 이용해 내가 만든 작업의 히스토리를 '시각적으로' 확인할 수 있게 되었습니다. 텍스트로만 보던 git log
와는 전혀 다른 경험이죠. 다음 모듈에서는 tig
의 다양한 뷰(View)를 탐험하며 Git의 상태를 속속들이 파헤쳐 보겠습니다.
모듈 2: Tig의 눈으로 Git 바라보기 (핵심 뷰)
강좌 목표: tig
의 기본 화면(Main View)을 넘어, 작업 현황(Status View), 브랜치 목록(Branch View), 코드 작성자 추적(Blame View) 등 핵심 뷰(View)를 자유자재로 넘나들며 Git의 상태를 입체적으로 파악합니다. tig
안에서 Git의 주요 명령어를 실행하는 경험을 통해 생산성을 극대화합니다.
1. Main View: 커밋 히스토리 여행하기 (심화)
모듈 1에서 우리는 tig
를 실행하면 가장 먼저 보이는 Main View를 만났습니다. 이곳은 우리 프로젝트의 시간 흐름, 즉 커밋 히스토리 전체를 보여주는 지도와 같습니다. 이제 이 지도를 더 깊이 탐험해 봅시다.
핵심 인터랙션: Enter
키로 커밋 내용 확인하기
tig
의 Main View에서 가장 중요한 기능 중 하나는 특정 커밋에서 정확히 무엇이 변경되었는지 즉시 확인하는 것입니다.
tig
를 실행하세요.- 키보드의
j
(아래),k
(위)를 이용해 확인하고 싶은 커밋으로 이동합니다. - 해당 커밋 위에서
Enter
키를 누르세요.
화면이 바뀌면서 선택한 커밋의 상세 변경 내역(Diff)이 나타납니다.
- 초록색
+
기호: 해당 커밋에서 추가된 라인입니다. - 빨간색
-
기호: 해당 커밋에서 삭제된 라인입니다.
이 화면에서 다시 q
키를 누르면 이전의 Main View로 돌아옵니다. 이 j/k
(이동) → Enter
(상세 보기) → q
(돌아가기) 흐름은 tig
사용의 가장 기본적인 리듬입니다.
실습: 모듈 1에서 만든
my-git-project
폴더로 이동하여README.md
파일을 열고 내용을 자유롭게 추가 및 삭제한 후 새로운 커밋을 만드세요. 그 다음tig
를 실행하여 각 커밋을 오가며Enter
키로 어떤 내용이 어떻게 변했는지 직접 확인하고q
키로 돌아오는 연습을 반복해보세요.
2. Status View: 내 작업 현황판
지금까지 수정한 내용, 새로 추가한 파일들을 커밋하기 전에 확인하려면 git status
명령어를 사용해야 했습니다. tig
의 Status View는 이 과정을 tig
안에서 훨씬 직관적으로 처리하게 해줍니다.
Status View로 전환하기: s
키
tig
의 아무 뷰에서나 s
(status) 키를 눌러보세요.
# tig 화면에서 's' 키를 누른 후의 예시
[main] ?? new-file.txt
[main] M README.md
--
status:
(u) Update (c) Commit (r) Revert
(s) Status (l) Log (q) Quit
화면 해석:
Unstaged changes
: 아직git add
하지 않은 변경사항 목록입니다. (??
: 추적하지 않는 새 파일,M
: 수정된 파일)Staged changes
:git add
를 통해 커밋 대기실(스테이징 영역)에 올라간 파일 목록입니다. (지금은 비어있음)
핵심 인터랙션: u
, C
로 커밋까지 한 번에!
Status View는 단순히 보여주기만 하는 것이 아니라, 직접 파일을 스테이징하고 커밋까지 할 수 있는 강력한 작업 공간입니다.
-
u
(update/unstage): 파일 스테이징/언스테이징Unstaged changes
목록에 있는 파일 위에서u
키를 누르면, 해당 파일이Staged changes
목록으로 이동합니다. (git add <file>
과 동일한 효과)- 반대로,
Staged changes
목록의 파일 위에서u
키를 누르면Unstaged changes
로 돌아옵니다. (git reset HEAD <file>
과 동일한 효과)
-
C
(Commit): 커밋하기- 스테이징할 파일들을 모두
u
키로 올렸다면, 대문자C
키를 누르세요. - 터미널의 기본 편집기(Vim, Nano 등)가 열리면서 커밋 메시지를 작성하는 화면이 나타납니다.
- 메시지를 작성하고 저장 후 종료하면, 커밋이 완료됩니다!
- 스테이징할 파일들을 모두
실습 (가장 중요한 실습!):
README.md
파일을 수정합니다.feature.txt
라는 새 파일을 만듭니다.tig
를 실행하고s
키를 눌러 Status View로 들어갑니다.README.md
와feature.txt
가Unstaged changes
에 있는 것을 확인합니다.j
,k
로 이동하며 각 파일 위에서u
키를 눌러Staged changes
로 옮겨보세요.C
키를 눌러 "Add new feature and update README" 라는 메시지로 커밋을 완료하세요.q
키로 Status View를 나와 Main View로 돌아가면, 방금 만든 커밋이 최상단에 추가된 것을 볼 수 있습니다. 이제 당신은tig
를 벗어나지 않고add
와commit
을 모두 수행했습니다!
3. Branch View & Refs View: 가지들 한눈에 보기
프로젝트가 커지면 여러 브랜치를 동시에 관리하게 됩니다. tig
는 흩어져 있는 모든 브랜치와 태그를 한 곳에서 보여줍니다.
b
(branch): 로컬 브랜치 목록을 보여줍니다.r
(refs): 로컬 브랜치, 원격 브랜치, 태그 등 모든 참조(Reference)를 보여줍니다. 보통r
을 더 자주 씁니다.
Refs View로 전환하기: r
키
tig
화면에서 r
키를 눌러보세요.
# 'r' 키를 누른 후의 예시
[refs]
HEAD
refs/heads/main
refs/heads/feature/login
refs/remotes/origin/main
refs/tags/v1.0
핵심 인터랙션: Enter
로 특정 브랜치 히스토리 필터링하기
Refs View의 진정한 힘은 '필터링' 기능에 있습니다.
r
키로 Refs View를 엽니다.- 보고 싶은 브랜치(예:
refs/heads/feature/login
)로 이동합니다. Enter
키를 누릅니다.
화면이 Main View로 바뀌면서, 오직 feature/login
브랜치에 해당하는 커밋 히스토리만 필터링되어 보입니다. 전체 히스토리를 다시 보고 싶다면, r
키로 돌아가 HEAD
에서 Enter
를 누르면 됩니다.
4. Blame View: 이 코드는 누가, 언제 수정했을까?
협업 시 "이 코드는 어떤 의도로 작성되었을까?" 궁금할 때가 많습니다. Blame View는 파일의 각 라인이 마지막으로 수정된 커밋 정보(작성자, 날짜, 커밋 해시)를 보여주는 강력한 추적 도구입니다.
Blame View로 진입하기: Main View → Diff View → B
키
Blame View는 진입 방법이 조금 다릅니다.
tig
의 Main View에서 특정 커밋을 선택하고 **Enter
**를 눌러 Diff View로 들어갑니다.- 파일 변경 내역이 보이는 이 화면에서, 추적하고 싶은 파일 섹션에 커서가 있을 때 대문자
B
키를 누릅니다.
이제 해당 파일의 전체 내용이 나타나며, 각 줄의 왼쪽에 누가, 언제, 어떤 커밋에서 이 라인을 수정했는지에 대한 정보가 표시됩니다. 버그의 원인이 된 코드를 찾았을 때, 이 기능을 사용하면 해당 변경사항의 맥락을 파악하고 담당자에게 질문하기가 매우 용이해집니다.
모듈 2 요약:
당신은 이제 tig
의 4대 핵심 뷰(Main, Status, Refs, Blame)를 모두 다룰 수 있게 되었습니다. 단순히 히스토리를 보는 것을 넘어, tig
안에서 직접 파일을 스테이징하고 커밋하며, 브랜치를 필터링하고, 코드의 역사를 추적하는 '능동적인' 사용자 되었습니다. 이제 tig
를 통해 Git의 가장 중요하고 흥미로운 기능인 '브랜치'를 시각적으로 다루어 볼 준비가 되었습니다. 다음 모듈 3에서는 브랜치를 만들고 합치는 과정을 tig
로 직접 눈으로 보며 마스터해 보겠습니다.
모듈 3: 브랜치 전략, Tig로 시각화하기
강좌 목표: Git의 꽃이라 불리는 '브랜치'의 개념을 완벽히 이해합니다. 브랜치를 만들고, 이동하고, 합치는(Merge, Rebase) 모든 과정을 tig
의 ASCII 그래프를 통해 시각적으로 추적하며, 복잡한 히스토리를 깔끔하게 관리하는 능력을 기릅니다.
1. 브랜치, 왜 써야 할까? (독립적인 작업 공간)
팀 프로젝트를 한다고 상상해 보세요. A
는 로그인 기능을 만들고, B
는 메인 페이지 디자인을 개선하고 있습니다. 만약 두 사람이 main
이라는 단 하나의 브랜치에서 동시에 작업한다면 어떻게 될까요?
- 아직 미완성인
A
의 로그인 코드가B
의 작업에 영향을 줄 수 있습니다. - 두 사람이 같은 파일을 수정하면 코드가 엉망이 될 수 있습니다. (충돌, Conflict)
- 갑자기 긴급한 버그를 수정해야 할 때, 현재 작업 중인 내용을 모두 되돌려야 하는 재앙이 발생합니다.
**브랜치(Branch)**는 이런 문제를 해결하기 위해, 기존 코드(보통 main
브랜치)의 특정 시점에서 새로운 가지를 만들어 독립적인 작업 공간을 제공하는 기능입니다.
- 안전성: 각자 자신의 브랜치에서 작업하므로 다른 사람의 작업에 영향을 주지 않습니다.
- 동시성: 여러 기능을 동시에 개발할 수 있습니다.
- 유연성: 기능 개발, 버그 수정, 테스트 등 목적에 따라 브랜치를 만들고, 작업이 끝나면 원래 브랜치와 합치거나 필요 없으면 버릴 수 있습니다.
결론: 브랜치는 안전하고 효율적인 협업을 위한 Git의 핵심 기능입니다.
2. 브랜치 생성과 전환, 그리고 시각화
이제 직접 브랜치를 만들고 tig
로 어떻게 보이는지 확인해 봅시다.
1. 새 브랜치 생성 및 이동 (Checkout)
현재 우리는 main
브랜치에 있습니다. "로그인 기능 개발"을 위한 feature/login
브랜치를 만들어 보겠습니다.
# 'feature/login' 브랜치를 생성하고, 그 브랜치로 즉시 이동(-b 옵션)
git checkout -b feature/login
git branch feature/login
과 git checkout feature/login
두 명령을 합친 것입니다.
2. 핵심: tig --all
로 전체 히스토리 보기
그냥 tig
만 실행하면 현재 브랜치(feature/login
)의 히스토리만 보입니다. 모든 브랜치를 함께 보려면 --all
옵션을 사용해야 합니다.
tig --all
tig
화면을 보면, 이제 main
과 feature/login
이 같은 커밋을 가리키고 있습니다. (HEAD -> feature/login, main)
처럼 표시될 것입니다. HEAD
는 "내가 지금 작업하는 곳"을 가리키는 포인터이며, 이제 feature/login
을 따라다닙니다.
3. 새 브랜치에서 커밋하기
feature/login
브랜치에서 로그인과 관련된 작업을 하고 커밋을 만들어 봅시다.
echo "Login form added" > login.html
git add login.html
git commit -m "Feat: Add login form structure"
4. 히스토리가 갈라지는 순간 확인하기
다시 tig --all
을 실행해 보세요. 마법 같은 순간이 펼쳐집니다.
# 'tig --all' 실행 예시
* 1a2b3c4 (HEAD -> feature/login) Feat: Add login form structure
|
* d4e5f6g (main) Update README with tig info
...
- ASCII 그래프:
feature/login
브랜치가main
브랜치에서 분기되어 새로운 커밋(1a2b3c4
)을 쌓아 올린 모습이 세로선|
과 별표*
로 명확하게 보입니다. - 포인터:
HEAD
와feature/login
은 새 커밋으로 이동했지만,main
은 예전 커밋에 그대로 머물러 있습니다.
이것이 바로
tig
의 힘입니다. 텍스트 명령어만으로는 상상해야 했던 '브랜치의 분기'를 직접 눈으로 확인하는 순간입니다.
3. Merge (병합): 가지를 하나로 합치기
feature/login
브랜치에서 기능 개발이 끝났다고 가정합시다. 이제 이 변경사항을 main
브랜치에 합쳐야 합니다. 이것을 **Merge(병합)**라고 합니다.
1. 합칠 대상 브랜치로 이동
main
브랜치에 feature/login
을 합칠 것이므로, main
브랜치로 돌아가야 합니다.
git checkout main
2. Merge 명령어 실행
main
브랜치에서, 합치고 싶은 브랜치(feature/login
)를 지정하여 병합합니다.
git merge feature/login
3. Merge 결과, tig
로 확인하기
다시 tig --all
을 실행해 보세요.
# 'tig --all' 실행 예시
* 5h6i7j8 (HEAD -> main) Merge branch 'feature/login'
|\
| * 1a2b3c4 (feature/login) Feat: Add login form structure
|/
* d4e5f6g Update README with tig info
...
- Merge Commit: "Merge branch 'feature/login'" 이라는 메시지를 가진 새로운 Merge Commit(
5h6i7j8
)이 생성되었습니다. 이 커밋은 두 개의 부모 커밋(기존main
의 마지막 커밋과feature/login
의 마지막 커밋)을 가집니다. - 그래프: 갈라졌던 두 브랜치가 Merge Commit을 통해 다시 하나로 합쳐지는 모습이
|\
와|/
같은 그래프로 명확하게 보입니다.main
과HEAD
포인터는 이제 이 Merge Commit을 가리킵니다.
4. Rebase (재배치): 히스토리 깔끔하게 만들기
Rebase는 Merge와 같이 브랜치를 합치는 또 다른 방법이지만, 동작 방식이 완전히 다릅니다. Rebase는 말 그대로 브랜치의 **베이스(Base, 기준점)를 재배치(Re-base)**하여 히스토리를 한 줄로 깨끗하게 만듭니다.
상황 설정: Merge를 되돌리고 Rebase를 해보기 위해, 방금 한 Merge를 취소해 봅시다. (tig
에서 Merge Commit 바로 이전 커밋의 해시(e.g., d4e5f6g
)를 확인하세요.)
# 이전 상태로 되돌리기 (주의: 이미 원격에 push한 커밋에는 사용하면 안 됩니다!)
git reset --hard d4e5f6g
1. Rebase 명령어 실행
feature/login
브랜치의 변경사항들을, main
브랜치의 최신 커밋 위로 옮겨 붙이겠습니다.
먼저 feature/login
브랜치로 이동해야 합니다.
git checkout feature/login
git rebase main
2. Rebase 결과, tig
로 확인하기
tig --all
로 결과를 확인하면, Merge와는 완전히 다른 모습에 놀라게 될 것입니다.
# 'tig --all' 실행 예시 (Rebase 후)
* 1a2b3c4' (HEAD -> feature/login) Feat: Add login form structure
* d4e5f6g (main) Update README with tig info
...
- 선형 히스토리: Merge처럼 히스토리가 갈라지고 합쳐지는 지저분한 그래프가 사라지고, 마치 처음부터
main
브랜치에서 순서대로 작업한 것처럼 히스토리가 한 줄로 깔끔하게 정리되었습니다. - 새로운 커밋 해시:
feature/login
의 커밋이었던1a2b3c4
가1a2b3c4'
처럼 새로운 해시값을 가진 커밋으로 재작성되었습니다. (Rebase는 기존 커밋을 복사해서 새로 만드는 과정이기 때문입니다.)
3. Fast-forward Merge
이제 main
브랜치로 돌아가서 merge
를 해보세요.
git checkout main
git merge feature/login
tig --all
을 보면, 별도의 Merge Commit 없이 main
포인터가 feature/login
의 위치로 '빨리 감기(Fast-forward)'처럼 쓱 이동한 것을 볼 수 있습니다. 히스토리가 매우 깨끗하게 유지됩니다.
Merge vs Rebase: 언제 무엇을 쓸까?
- Merge: "두 브랜치를 합쳤다"는 사실 자체를 히스토리에 명확히 남기고 싶을 때 사용합니다. 팀의 공식적인 히스토리에 적합합니다.
- Rebase: 브랜치가 너무 지저분하게 뻗어 나가는 것을 방지하고, 최종적으로
main
에 합치기 전에 내 작업 히스토리를 깔끔하게 정리하고 싶을 때 사용합니다. (특히 개인 브랜치에서)
경고: 이미 팀원과 공유한(원격 저장소에
push
한) 브랜치에서는 절대rebase
를 사용하면 안 됩니다. 다른 팀원의 히스토리와 충돌하여 큰 혼란을 일으킬 수 있습니다.
모듈 3 요약:
당신은 이제 Git 브랜치의 핵심인 분기(Branching), 병합(Merge), 재배치(Rebase)의 개념을 tig
를 통해 눈으로 직접 확인하며 완벽히 이해했습니다. 지저분한 Merge 히스토리와 깔끔한 Rebase 히스토리의 차이를 시각적으로 비교함으로써, 언제 어떤 전략을 써야 할지 판단하는 능력을 갖추게 되었습니다. 이제 이 로컬에서의 경험을 바탕으로, 다음 모듈에서는 다른 사람과 협업하기 위한 '원격 저장소'와의 상호작용을 배워보겠습니다.
모듈 4: 협업의 시작 - 원격 저장소와 Tig
강좌 목표: 로컬 저장소의 작업을 GitHub과 같은 원격 저장소와 동기화하는 방법을 배웁니다. push
, pull
, fetch
명령어의 차이점을 tig
의 origin/main
과 같은 원격 브랜치 포인터의 움직임을 통해 명확하고 직관적으로 이해합니다. 이를 통해 팀원들과 코드를 안전하게 공유하고 최신 상태를 유지하는 능력을 기릅니다.
1. 원격 저장소(Remote) 연동
지금까지 우리의 모든 작업(커밋
, 브랜치
)은 개인 컴퓨터, 즉 **로컬 저장소(Local Repository)**에만 저장되어 있습니다. 협업을 하려면 이 작업 내역을 모든 팀원이 접근할 수 있는 중앙 서버, 즉 **원격 저장소(Remote Repository)**에 올려야 합니다. 가장 대표적인 원격 저장소 서비스가 바로 GitHub입니다.
1. GitHub에 새 원격 저장소 생성하기
- GitHub에 접속하여 로그인합니다.
- 우측 상단의 '+' 버튼 또는 'New' 버튼을 눌러 새 저장소를 만듭니다.
- 저장소 이름은 로컬 프로젝트와 동일하게
my-git-project
로 설정합니다. - 중요:
Initialize this repository with a README
옵션은 체크 해제합니다. 우리는 이미 로컬에 작업 내역이 있기 때문입니다. - 'Create repository' 버튼을 클릭합니다.
2. 로컬 저장소에 원격 저장소 주소 등록하기
저장소가 생성되면, GitHub는 친절하게도 "...or push an existing repository from the command line" 이라는 안내를 보여줍니다. 이 안내문의 명령어를 사용하면 됩니다.
# 'origin'이라는 별명으로 원격 저장소 주소를 등록합니다.
git remote add origin https://github.com/YourUsername/my-git-project.git
# 등록된 원격 저장소 정보를 확인합니다.
git remote -v
origin
: 원격 저장소 주소에 붙이는 기본 별명입니다. 다른 이름으로 지정할 수도 있지만,origin
이 관례입니다.- 이제 Git은
origin
이라는 단어가 GitHub에 있는 우리 저장소를 의미한다는 것을 압니다.
2. Push & Pull: 내 코드를 공유하고, 동료 코드를 가져오기
Push: 내 로컬 작업을 원격 저장소에 올리기 (업로드)
push
는 내 컴퓨터(로컬)의 커밋들을 원격 저장소(origin
)로 전송하여 팀원들과 공유하는 명령어입니다.
# 현재 로컬의 'main' 브랜치를 원격 'origin'의 'main' 브랜치로 push 합니다.
# -u 옵션은 앞으로 이 로컬 브랜치가 원격의 해당 브랜치를 추적하도록 설정하는 것입니다. (최초 한번만)
git push -u origin main
- 핵심:
tig
로 Push 결과 확인하기**
push
가 성공적으로 완료된 후, tig --all
을 실행해 보세요.
# 'tig --all' 실행 예시 (Push 후)
* ... (HEAD -> main, origin/main) Latest commit
...
origin/main
포인터 등장: 이전에는 보이지 않던origin/main
이라는 새로운 포인터가 생겼습니다! 이것은 원격 저장소origin
의main
브랜치가 어디까지 알고 있는지를 나타냅니다.- 동일한 위치:
push
를 했기 때문에, 로컬main
과 원격origin/main
은 현재 동일한 최신 커밋을 가리키고 있습니다.
Pull: 원격 저장소의 최신 작업을 내 로컬로 가져오기 (다운로드 + 병합)
이제 다른 팀원이 새로운 작업을 push
했다고 상상해 봅시다. 우리는 그 최신 내용을 우리 로컬 컴퓨터로 가져와야 합니다. 이 때 pull
명령어를 사용합니다.
(실습을 위해 GitHub 사이트에서 직접 README.md
파일을 수정하여 새 커밋을 만들어 봅시다.)
- GitHub의
my-git-project
저장소 페이지로 이동합니다. README.md
파일을 클릭하고, 연필 모양(Edit) 아이콘을 눌러 내용을 수정한 뒤, "Commit changes" 버튼을 눌러 커밋합니다.
이제 원격 저장소는 우리 로컬보다 한 발 앞서 나간 상태입니다. 이 변경사항을 가져와 봅시다.
git pull origin main
- 핵심:
tig
로 Pull 결과 확인하기**
pull
명령 후 tig --all
을 다시 실행하면,
# 'tig --all' 실행 예시 (Pull 후)
* ... (HEAD -> main, origin/main) Commit from GitHub
* ... Previous local commit
...
- 포인터 동기화:
pull
을 통해 원격 저장소의 새 커밋이 로컬로 다운로드되고, 로컬main
브랜치에 병합(merge)되었습니다. 그 결과,HEAD
,main
,origin/main
포인터가 모두 다시 최신 커밋을 함께 가리키게 됩니다.
3. Fetch vs Pull 명확히 이해하기
많은 입문자들이 fetch
와 pull
의 차이를 헷갈려 합니다. tig
는 이 둘의 차이를 명확하게 보여주는 최고의 교사입니다.
결론부터 말하면:
git pull
=git fetch
+git merge
입니다.
fetch
: 일단 가져와서 보기만 할게 (다운로드)
fetch
는 원격 저장소의 최신 변경 내역을 로컬로 가져오되, 내 작업 브랜치(main
)와 자동으로 합치지는 않습니다. 단지 "원격 저장소는 이런 변경사항이 있구나" 하고 정보만 업데이트하는 것입니다.
pull
: 가져와서 합치기까지 할게 (다운로드 + 병합)
pull
은 fetch
를 수행한 다음, 가져온 내용을 현재 내 작업 브랜치와 즉시 merge
까지 해버립니다.
- 실습:
tig
로fetch
와pull
의 차이 눈으로 보기**
-
상황 만들기: 다시 GitHub 사이트에서
README.md
파일을 한번 더 수정하고 커밋합니다. 이제 원격 저장소가 다시 앞서 나갑니다. -
fetch
실행: 이번에는pull
대신fetch
를 실행합니다.git fetch origin
-
tig
로fetch
결과 확인:tig --all
을 실행해 보세요. 이것이 가장 중요한 순간입니다.# 'tig --all' 실행 예시 (Fetch 후) * ... (origin/main) New commit from GitHub | * ... (HEAD -> main) My previous commit ...
- 포인터 분리!
origin/main
포인터는 GitHub에서 새로 만든 커밋으로 혼자 이동했습니다. 원격의 최신 정보를 반영한 것이죠.- 하지만
HEAD -> main
포인터는 이전 커밋에 그대로 머물러 있습니다!fetch
는 내 작업을 전혀 건드리지 않았다는 명확한 증거입니다.
- 포인터 분리!
-
수동으로 Merge 하기: 이제
main
브랜치에origin/main
의 변경사항을 직접 합쳐봅시다.git merge origin/main
-
tig
로 최종 결과 확인:tig --all
을 다시 실행하면,main
포인터가origin/main
의 위치로 이동하며 합쳐지고, 두 포인터가 다시 같은 커밋을 가리키는 것을 볼 수 있습니다. 이 결과는git pull
을 실행했을 때와 동일합니다.
언제
fetch
를 쓸까? 동료가 어떤 작업을 했는지 내 로컬 브랜치에 영향을 주지 않고 미리 확인하고 싶을 때 매우 유용합니다.fetch
로 변경사항을 가져온 뒤,tig
로origin/main
의 히스토리를 쭉 훑어보고, 준비가 되었을 때merge
를 실행하는 것이 훨씬 안전한 워크플로우입니다.
모듈 4 요약:
당신은 이제 로컬 작업을 원격 저장소에 공유(push
)하고, 팀원의 작업을 내 로컬로 가져오는(pull
) 방법을 마스터했습니다. 더 나아가, tig
의 원격 브랜치 포인터(origin/main
)의 움직임을 통해 fetch
와 pull
의 근본적인 차이점을 시각적으로 완벽하게 이해했습니다. 이제 당신은 Git을 이용한 기본적인 팀 협업을 수행할 준비가 되었습니다. 다음 모듈에서는 과거의 실수를 바로잡거나, 필요한 커밋만 쏙쏙 가져오는 등 Git의 강력한 시간 여행 기술들을 배워보겠습니다.
모듈 5: 시간 여행과 문제 해결 (고급 스킬)
강좌 목표: 잘못된 커밋을 안전하게 되돌리고(revert
), 과거의 특정 시점으로 돌아가며(reset
), 다른 브랜치의 유용한 커밋만 가져오고(cherry-pick
), 지저분한 커밋 히스토리를 재구성하는(rebase -i
) 등 Git의 강력한 시간 여행 기술들을 마스터합니다. 이 모든 위험할 수 있는 작업들을 tig
를 통해 시각적으로 확인하며 안전하고 자신감 있게 수행하는 능력을 기릅니다.
1. revert
: 안전하게 과거 되돌리기
실수로 버그가 있는 코드를 커밋하고 push
까지 해버렸다면 어떻게 할까요? 히스토리를 강제로 삭제하는 reset
은 팀원들에게 혼란을 줄 수 있어 위험합니다. 이럴 때 **revert
**를 사용합니다. revert
는 특정 커밋의 변경사항을 취소하는 새로운 커밋을 만들어 문제를 해결합니다.
1. 문제 상황 만들기
먼저, 버그를 포함한 커밋을 만들어 원격 저장소에 push
까지 해봅시다.
echo "This is a critical bug!" >> bug.txt
git add bug.txt
git commit -m "Feat: Add new feature (with a bug)"
git push origin main
2. tig
로 되돌릴 커밋 확인 및 해시 복사
tig
를 실행하여 방금 만든 "Feat: Add new feature (with a bug)" 커밋을 찾으세요. 커밋 라인의 맨 앞에 있는 a1b2c3d
같은 7자리의 **커밋 해시(hash)**가 필요합니다. tig
화면에서 해당 커밋 위에 커서를 놓고 y
키를 누르면 해시 값이 클립보드에 복사됩니다.
3. revert
실행
복사한 해시를 사용하여 revert
명령을 실행합니다.
# a1b2c3d 부분에 방금 복사한 해시를 붙여넣으세요.
git revert a1b2c3d
이 명령을 실행하면 커밋 메시지 편집기가 열립니다. 기본 메시지("Revert '...'")를 그대로 사용하거나 수정 후 저장하고 종료합니다.
4. tig
로 결과 확인
tig
를 다시 실행해 보세요.
# 'tig' 실행 예시 (Revert 후)
* 4e5f6g7 (HEAD -> main) Revert "Feat: Add new feature (with a bug)"
* a1b2c3d (origin/main) Feat: Add new feature (with a bug)
...
- 새로운 Revert 커밋: 기존의 버그 커밋(
a1b2c3d
)은 그대로 남아있고, 그 위에 "Revert..."라는 새로운 커밋(4e5f6g7
)이 쌓였습니다. - 안전한 히스토리: 이
Revert
커밋의 내용을Enter
로 확인해 보면, 버그 커밋에서 했던 변경사항을 정확히 반대로 수행(파일을 삭제하거나, 추가했던 내용을 삭제)한 것을 볼 수 있습니다. 기존 히스토리를 삭제하지 않고 새로운 커밋을 추가하여 문제를 해결했기 때문에 팀원들과 공유하기에 매우 안전합니다.
2. reset
: 강력하지만 위험한 과거 바꾸기
reset
은 브랜치 포인터를 특정 과거 커밋으로 강제로 이동시켜, 그 이후의 커밋들을 히스토리에서 사라지게 만드는 강력한 도구입니다. 아직 push
하지 않은, 로컬에만 있는 실수를 바로잡을 때 매우 유용합니다.
--soft
, --mixed
(기본값), --hard
옵션의 차이
-
--soft
: 커밋만 취소. 변경된 파일 내용은 스테이징 영역(git add
한 상태)에 그대로 남아있음. -
--mixed
: 커밋과 스테이징을 모두 취소. 변경된 파일 내용은 워킹 디렉토리(수정만 한 상태)에 남아있음. -
--hard
: (주의!) 커밋, 스테이징, 워킹 디렉토리의 변경 내용을 모두 삭제. 해당 시점 이후의 모든 작업이 영구적으로 사라짐. -
실습:
reset --hard
의 파괴력tig
로 확인하기**
-
상황 만들기: 로컬에서만 두 개의 잘못된 커밋을 만들었다고 가정합시다.
echo "Mistake 1" > mistake.txt git add . && git commit -m "Oops, mistake 1" echo "Mistake 2" >> mistake.txt git add . && git commit -m "Oops, mistake 2"
-
tig
로 현재 상태와 돌아갈 지점 확인tig
를 켜서 방금 만든 두 개의 "Oops" 커밋과, 그 이전의 정상적인 커밋을 확인하세요. 정상 커밋의 해시를y
로 복사합니다. -
reset --hard
실행# 복사한 정상 커밋의 해시를 붙여넣으세요. git reset --hard <정상_커밋_해시>
-
tig
로 결과 확인tig
를 다시 실행하면, "Oops" 커밋 두 개가 히스토리에서 완전히 사라진 것을 볼 수 있습니다.ls
명령어로 파일 목록을 봐도mistake.txt
파일이 사라졌습니다.reset --hard
는 이렇게 과거를 없었던 일로 만들어 버립니다.
경고:
reset
은 히스토리를 재작성하므로, 이미 팀원과 공유한(push
한) 커밋에는 절대 사용하지 마세요. 꼭 필요하다면revert
를 사용해야 합니다.
3. cherry-pick
: 필요한 커밋만 쏙쏙 가져오기
feature/A
브랜치에서 작업한 5개의 커밋 중, 딱 1개의 커밋(예: 유용한 유틸리티 함수)만 지금 당장 main
브랜치에도 적용하고 싶을 때가 있습니다. 이럴 때 **cherry-pick
**을 사용하면 해당 커밋 하나만 '체리처럼 쏙 따서' 내 브랜치에 복사해올 수 있습니다.
1. 상황 만들기
-
feature/new-util
이라는 브랜치를 만듭니다. -
해당 브랜치에서 2개의 커밋을 만듭니다. (하나는 불필요한 커밋, 다른 하나는 유용한 커밋)
git checkout -b feature/new-util echo "useless" > temp.txt && git add . && git commit -m "WIP: temporary work" echo "export const useful = () => {}" > util.js && git add . && git commit -m "Feat: Add a very useful utility"
2. tig
로 가져올 커밋 확인 및 해시 복사
main
브랜치로 돌아옵니다. (git checkout main
)tig --all
을 실행하여feature/new-util
브랜치를 봅니다.- 가져오고 싶은 "Feat: Add a very useful utility" 커밋을 찾아 해시를
y
로 복사합니다.
3. cherry-pick
실행
git cherry-pick <복사한_유틸리티_커밋_해시>
4. tig
로 결과 확인
tig
를 실행해 보면, main
브랜치의 최상단에 "Feat: Add a very useful utility" 커밋이 그대로 복사되어 들어온 것을 볼 수 있습니다. feature/new-util
브랜치의 불필요한 커밋은 가져오지 않았습니다.
4. rebase -i
: 인터랙티브 리베이스로 커밋 재구성하기
push
하기 전에, 너무 자잘하게 만든 커밋들을 하나의 의미 있는 커밋으로 합치거나(squash), 커밋 메시지를 수정하고 싶을 때 **인터랙티브 리베이스(rebase -i
)**를 사용합니다. 히스토리를 예술 작품처럼 다듬는 과정입니다.
1. 상황 만들기: 로컬에서 자잘한 커밋 3개를 만들었다고 가정합니다.
echo "1" > work.txt && git add . && git commit -m "fix: typo"
echo "2" >> work.txt && git add . && git commit -m "add part of feature"
echo "3" >> work.txt && git add . && git commit -m "complete the feature and fix style"
2. tig
로 재구성할 커밋 범위 확인
tig
를 켜면 방금 만든 3개의 너저분한 커밋이 보입니다. 이 3개의 커밋을 정리할 것입니다. 현재 위치(HEAD
)로부터 3개 이전까지를 의미하는 HEAD~3
을 범위로 사용합니다.
3. rebase -i
실행
git rebase -i HEAD~3
4. 인터랙티브 화면에서 히스토리 편집 이 명령을 실행하면, 다음과 같은 편집기 화면이 나타납니다.
pick a1b2c3d fix: typo
pick b2c3d4e add part of feature
pick c3d4e5f complete the feature and fix style
# Commands:
# p, pick = use commit
# s, squash = use commit, but meld into previous commit
...
-
맨 위 커밋(
a1b2c3d
)은pick
(그대로 둠)으로 놔두고, -
아래 두 개의 커밋 앞 단어
pick
을s
(또는squash
)로 바꿉니다. -
pick
→s
로 변경:pick a1b2c3d fix: typo s b2c3d4e add part of feature s c3d4e5f complete the feature and fix style
-
편집기를 저장하고 종료하면, 3개 커밋의 메시지를 하나로 합치는 두 번째 편집기 창이 열립니다. 여기서 최종 커밋 메시지(예: "Feat: Implement the full feature")를 깔끔하게 작성하고 저장, 종료합니다.
5. tig
로 결과 확인
tig
를 다시 실행해 보세요. 너저분했던 3개의 커밋이 하나의 깔끔한 커밋으로 합쳐진 마법 같은 결과를 볼 수 있습니다. 이제 이 잘 정리된 커밋을 push
하면 됩니다.
모듈 5 요약:
당신은 이제 Git의 가장 강력한 시간 여행 도구들을 자유자재로 다룰 수 있게 되었습니다. tig
를 나침반 삼아, 안전하게 실수를 되돌리고(revert
), 로컬 히스토리를 정리하며(reset
, rebase -i
), 필요한 작업만 쏙쏙 가져오는(cherry-pick
) 방법을 체득했습니다. 이는 단순한 명령어 사용을 넘어, 복잡한 프로젝트 히스토리를 자신감 있게 관리하는 'Git 전문가'로 가는 중요한 발판입니다. 마지막 모듈에서는 이 모든 기술을 내 손에 맞게 최적화하는 방법을 배우겠습니다.
모듈 6: Tig, 나만의 무기로 만들기 (최적화 및 활용)
강좌 목표: 지금까지 배운 tig
의 기능들을 조합하여 자신만의 효율적인 Git 워크플로우를 만듭니다. 자주 사용하는 단축키와 팁을 익히고, .tigrc
설정 파일을 통해 tig
의 외형과 동작을 커스터마이징하여 생산성을 극대화합니다. tig
를 '그냥 사용하는 도구'에서 '내 손에 꼭 맞는 무기'로 진화시킵니다.
1. 나만의 Tig 워크플로우 만들기
숙련된 개발자는 매일 반복하는 작업을 자신만의 루틴으로 만듭니다. tig
를 사용하면 Git과 관련된 거의 모든 일상 업무를 터미널을 벗어나지 않고, 일관된 흐름으로 처리할 수 있습니다.
예시: "나의 하루" 워크플로우
아침에 출근해서 어제 하던 작업을 이어가는 상황을 가정해 봅시다.
-
(S) 상태 확인: 터미널을 열고 프로젝트 폴더에서
tig
를 실행합니다. 가장 먼저s
키를 눌러 Status View로 들어갑니다.- 어제 작업하다가 커밋하지 않은 파일은 없는지? (
Unstaged changes
) - 실수로 추가된 불필요한 파일은 없는지?
- Action:
tig
화면에서 바로 어제의 변경 사항을 확인합니다.
- 어제 작업하다가 커밋하지 않은 파일은 없는지? (
-
(F) 동료 작업 확인: **
q
**로 Main View로 돌아와,F
키(대문자)를 누릅니다. (git fetch
와 동일)tig
가 원격 저장소(origin
)의 최신 정보를 가져옵니다.origin/main
포인터가 앞으로 이동했다면, 밤새 동료가 새로운 작업을push
했다는 의미입니다.- Action:
j
,k
로origin/main
까지 이동하며 동료의 커밋 내용을Enter
로 훑어봅니다. 내 작업과 충돌할 부분이 있는지 미리 파악할 수 있습니다.
-
(M) 최신 내용 병합:
origin/main
의 내용을 내 로컬 브랜치로 합칩니다.- 안전한 방법:
tig
화면에서M
키(대문자)를 누릅니다.Merge...?
프롬프트가 뜨면origin/main
을 입력하고 엔터. (git merge origin/main
과 동일) - Rebase 선호 시: 터미널에서
git rebase origin/main
을 실행하고tig
로 결과를 확인합니다.
- 안전한 방법:
-
(작업 & 커밋): 이제 내 할 일을 합니다. 코드를 작성하고 수정합니다.
- 어느 정도 작업이 완료되면, 다시
tig
를 켜고s
(Status View)로 갑니다. u
키로 스테이징하고,C
(대문자) 키로 커밋합니다. (모듈 2에서 배운 내용) 이 과정을 반복합니다.
- 어느 정도 작업이 완료되면, 다시
-
(P) 작업 내용 공유: 퇴근 전, 오늘 작업한 내용을
push
합니다.tig
화면에서P
키(대문자)를 누릅니다.Push...?
프롬프트가 뜨면 엔터를 누릅니다. (git push
와 동일)
이 워크플로우의 장점:
tig
라는 단일 인터페이스 안에서 상태 확인 → 동료 작업 확인 → 병합 → 내 작업 → 커밋 → 공유까지의 모든 사이클이 끊김 없이 이어집니다. 컨텍스트 전환 비용이 줄어들어 개발에 더 집중할 수 있습니다.
2. 유용한 단축키와 팁 (생산성 부스터)
tig
에는 숨겨진 보석 같은 기능들이 많습니다. 이것들만 알아도 작업 속도가 몇 배는 빨라집니다.
-
/
(검색): Main View에서/
를 누르고 키워드를 입력하면, 커밋 메시지, 작성자, 파일명 등에서 해당 키워드를 포함한 커밋을 찾아 하이라이트해 줍니다.n
(다음),N
(이전)으로 검색 결과 간 이동이 가능합니다. "특정 티켓 번호(#123)와 관련된 모든 커밋 찾기" 등에 매우 유용합니다. -
@<file>
(특정 파일 히스토리 보기):tig
를 실행할 때 파일 경로를 함께 주면, 해당 파일의 변경 이력만 필터링해서 보여줍니다.tig -- README.md # 또는 tig 실행 후, :log README.md 입력
README.md
파일이 언제, 누구에 의해, 어떻게 변해왔는지 한눈에 볼 수 있습니다. -
L
(상세 로그 보기): Main View에서 커밋을 선택하고L
(대문자) 키를 누르면git show
명령어처럼 해당 커밋의 메타데이터와 전체 변경 내용을 한 번에 보여줍니다. -
h
(도움말): 어떤 뷰에서든h
키를 누르면 해당 뷰에서 사용할 수 있는 모든 단축키 목록을 보여줍니다.tig
의 모든 기능을 외울 필요가 없습니다. 궁금할 땐h
를 누르세요.
3. .tigrc
파일로 커스터마이징하기
tig
의 진정한 화룡점정은 .tigrc
설정 파일을 통해 나만의 도구로 튜닝하는 것입니다. 이 파일은 보통 홈 디렉토리(~/.tigrc
)에 만듭니다.
1. .tigrc
파일 생성
touch ~/.tigrc
이제 이 파일을 텍스트 편집기로 열어 원하는 설정을 추가하면 됩니다.
2. 추천 커스터마이징 설정 예시
아래 내용을 ~/.tigrc
파일에 복사/붙여넣기하고 tig
를 다시 실행해 보세요.
# .tigrc 예시
# 1. Main View에 브랜치/태그 정보를 항상 표시 (가장 유용한 설정!)
set main-view = date author:20,width=20 refs commit-title:*,wrap
set line-graphics = utf-8 # ASCII 그래프를 더 예쁜 문자로 표시
# 2. 작성자 이름 대신 이메일 주소 일부를 표시 (옵션)
# set author-display = email
# 3. 자주 사용하는 명령 단축키로 바인딩하기
# Main View에서 대문자 P를 누르면 git push가 바로 실행됨
bind main P !git push
# Main View에서 대문자 F를 누르면 git fetch --prune이 바로 실행됨
# (--prune: 원격에서 삭제된 브랜치를 로컬에서도 깔끔하게 정리해주는 옵션)
bind main F !git fetch --prune
# 4. 색상 테마 변경하기 (기본, blue, black 등)
# set color-scheme = blue
설정 설명:
set main-view = ...
:tig
의 메인 화면에 표시될 정보의 종류와 너비를 지정합니다. 위 설정은refs
(브랜치/태그)를 항상 보여주게 하여tig --all
을 매번 입력할 필요가 없게 만듭니다.set line-graphics = utf-8
:|
,*
같은 기본 ASCII 문자를│
,●
등 더 보기 좋은 특수문자로 바꿔줍니다.bind <view> <key> <command>
: 특정 뷰(main
,status
등)에서 특정 키(<key>
)를 눌렀을 때 실행될 외부 명령어(<command>
)를 지정합니다.!git push
처럼 앞에!
를 붙이면 쉘 명령을 실행할 수 있습니다. 위 예시는P
키로 푸시,F
키로 페치를 바로 실행하게 해줍니다.
맺음말: 이제 Git이 두렵지 않습니다
이 강좌를 통해 여러분은 Git의 기본적인 개념부터 브랜치 전략, 협업, 그리고 과거를 제어하는 고급 기술까지 tig
라는 훌륭한 나침반과 함께 항해했습니다.
- 여러분은 이제:
- 복잡한 Git 히스토리를 한눈에 파악하고,
- CLI 환경에서 마우스 없이 빠르고 효율적으로 Git을 다루며,
- Merge와 Rebase의 차이를 시각적으로 설명할 수 있고,
revert
,cherry-pick
같은 고급 기술을 자신감 있게 사용할 수 있으며,tig
를 자신만의 워크플로우에 맞게 최적화할 수 있게 되었습니다.
Git은 더 이상 두려움의 대상이 아닙니다. tig
와 함께라면 Git은 여러분의 가장 강력하고 신뢰할 수 있는 개발 파트너가 될 것입니다. 여기서 멈추지 말고, GitHub Flow, Git-flow와 같은 팀의 브랜치 전략론을 학습하며 더 큰 규모의 협업에 도전해 보세요.
보너스 모듈 7: 충돌(Conflict) 해결의 기술
강좌 목표: Git 협업의 필연적인 과정인 '충돌(Conflict)'을 더 이상 두려워하지 않고, 체계적으로 해결하는 능력을 기릅니다. tig
를 통해 충돌 상황을 인지하고, 표준적인 도구를 이용해 해결한 뒤, 깔끔하게 정리된 히스토리를 시각적으로 확인합니다.
1. 충돌은 왜, 언제 발생하는가?
충돌은 Git의 오류가 아니라, 의사소통이 필요한 시점이라는 신호입니다. Git이 두 개의 다른 브랜치를 합치려 할 때, 같은 파일의 같은 라인을 서로 다르게 수정한 내역을 발견하면 자동으로 결정할 수 없습니다. 이때 Git은 작업을 멈추고 사용자에게 "이 부분은 어떻게 합쳐야 할지 당신이 직접 결정해 주세요"라고 요청합니다. 이것이 바로 충돌입니다.
2. Merge 충돌 시뮬레이션 및 해결
가장 흔한 Merge 충돌 상황을 직접 만들고 해결해 봅시다.
1. 충돌 상황 만들기
-
main
브랜치에서team-rules.md
파일을 만듭니다.git checkout main echo "# 우리 팀의 규칙" > team-rules.md echo "- 1. 일찍 출근하기" >> team-rules.md git add . && git commit -m "Docs: 팀 규칙 초기 버전 작성"
-
이제
feature/rule-update
브랜치를 만들어 규칙을 수정합니다.git checkout -b feature/rule-update # 1번 규칙을 수정 sed -i '' 's/일찍 출근하기/정시 출근하기/' team-rules.md # macOS # sed -i 's/일찍 출근하기/정시 출근하기/' team-rules.md # Linux git add . && git commit -m "Feat: 출근 규칙 현실화"
-
그런데 그 사이, 다른 팀원이
main
브랜치에서 같은 라인을 다르게 수정했다고 가정합시다.git checkout main # 1번 규칙을 또 다르게 수정 sed -i '' 's/일찍 출근하기/자율 출근하기/' team-rules.md # macOS # sed -i 's/일찍 출근하기/자율 출근하기/' team-rules.md # Linux git add . && git commit -m "Feat: 자율 출근 제도로 변경"
2. 충돌 발생시키기
이제 main
브랜치에서 feature/rule-update
브랜치를 merge
해봅시다.
git merge feature/rule-update
터미널에 CONFLICT (content): Merge conflict in team-rules.md
와 같은 메시지가 뜨며 작업이 멈춥니다.
3. tig
로 충돌 상태 확인하기
이때 tig
를 실행하고 s
키를 눌러 Status View를 보면, 충돌의 증거를 명확히 볼 수 있습니다.
# Status View 예시
[main|MERGING] UU team-rules.md
--
status:
Unmerged paths:
(u)se stage 1 (base) (2)se stage 2 (ours) (3)se stage 3 (theirs)
[main|MERGING]
: 브랜치 이름 옆에MERGING
상태가 표시됩니다.UU
: Unmerged, both updated. 양쪽 브랜치에서 모두 수정되어 병합하지 못했다는 의미입니다.
4. 충돌 해결하기 (VS Code 활용) 충돌은 텍스트 편집기에서 직접 해결합니다. VS Code와 같은 최신 편집기는 이 과정을 매우 편리하게 도와줍니다.
-
터미널에서
code .
를 입력해 VS Code를 엽니다. -
team-rules.md
파일을 열면, 충돌 부분이 다음과 같이 표시됩니다.# 우리 팀의 규칙 <<<<<<< HEAD - 1. 자율 출근하기 ======= - 1. 정시 출근하기 >>>>>>> feature/rule-update
-
해석:
<<<<<<< HEAD
:HEAD
(현재 브랜치, 즉main
)의 내용입니다.=======
: 양쪽 브랜치 내용의 구분선입니다.>>>>>>> feature/rule-update
: 병합하려던 브랜치(feature/rule-update
)의 내용입니다.
-
VS Code는 이 구문 위에 [Accept Current Change] | [Accept Incoming Change] | [Accept Both Changes] 와 같은 편리한 버튼을 제공합니다.
-
여기서는 팀원과 논의 후, "자율 출근"으로 결정했다고 가정하고 [Accept Current Change] 를 클릭합니다. 또는, 직접 키보드로 해당 라인들을 지우고 최종 합의된 내용(예:
- 1. 논의 후 자율 출근으로 결정
)으로 수정합니다.
5. 해결 완료 알리기 충돌 부분을 말끔하게 정리하고 파일을 저장했다면, Git에게 "해결 완료!"라고 알려주어야 합니다.
git add team-rules.md
git commit
git commit
시 -m
옵션을 주지 않으면, Git이 자동으로 "Merge branch '...'" 라는 커밋 메시지가 포함된 편집기 창을 열어줍니다. 그대로 저장하고 종료하면 됩니다.
6. tig
로 최종 결과 확인
다시 tig --all
을 실행하면, 언제 충돌이 있었냐는 듯 깔끔한 Merge Commit이 생성되고 히스토리가 성공적으로 합쳐진 것을 시각적으로 확인할 수 있습니다.
보너스 모듈 8: 실전 브랜치 전략: Git-flow vs GitHub Flow
강좌 목표: 대표적인 두 가지 실전 브랜치 전략의 개념과 차이점을 이해합니다. tig
의 그래프를 통해 각 전략이 어떤 히스토리 모양을 만드는지 시각적으로 비교하고, 내 프로젝트에 어떤 전략이 더 적합할지 판단하는 능력을 기릅니다.
1. Git-flow: 체계적인 대규모 프로젝트를 위한 전략
Git-flow는 여러 종류의 브랜치가 각자의 명확한 역할을 가지고 상호작용하는, 다소 복잡하지만 매우 체계적인 전략입니다. 버전 릴리즈가 중요한 소프트웨어(ex: 데스크톱 앱, 모바일 앱)에 적합합니다.
-
주요 브랜치:
main
(또는master
): 배포된 버전의 코드만 모아두는 가장 안정적인 브랜치. 직접 커밋하지 않음.develop
: 다음 버전에 포함될 기능들이 통합되는 개발의 중심 브랜치.
-
보조 브랜치:
feature/*
: 새로운 기능 개발을 위한 브랜치.develop
에서 분기하여 작업 후, 다시develop
으로 병합.release/*
: 배포 준비를 위한 브랜치.develop
에서 분기하여 버전 넘버링, 최종 버그 수정 등을 진행. 완료되면main
과develop
양쪽에 모두 병합.hotfix/*
: 긴급 버그 수정을 위한 브랜치.main
에서 직접 분기하여 수정 후,main
과develop
양쪽에 모두 병합.
-
tig
로 본 Git-flow 히스토리:**tig --all
로 보면, 여러 줄기의 브랜치가 복잡하게 얽히고설키는 모습을 보입니다.feature
는develop
으로,release
와hotfix
는main
과develop
양쪽으로 합쳐지는 복잡하지만 질서정연한 그래프가 그려집니다.
2. GitHub Flow: 빠르고 지속적인 배포를 위한 전략
GitHub Flow는 Git-flow의 복잡성을 대폭 줄인, 매우 단순하고 빠른 전략입니다. 웹 애플리케이션처럼 수시로 배포가 일어나는 프로젝트(CI/CD)에 매우 적합합니다.
-
핵심 원칙:
main
브랜치는 언제나 배포 가능한 상태로 유지한다. -
워크플로우:
- 새로운 작업(기능, 버그 수정 등)이 필요하면
main
에서 설명적인 이름의 브랜치(feature/user-auth
,fix/login-bug
등)를 만든다. - 해당 브랜치에서 자유롭게 커밋하며 작업한다.
- 작업이 완료되면 원격 저장소에
push
하고 **Pull Request(PR)**를 생성한다. - PR을 통해 팀원들의 코드 리뷰를 받고, 자동화된 테스트를 통과시킨다.
- 리뷰와 테스트가 모두 통과되면, 해당 브랜치를
main
에 병합하고 즉시 배포한다.
- 새로운 작업(기능, 버그 수정 등)이 필요하면
-
tig
로 본 GitHub Flow 히스토리:**tig --all
로 보면, 마치 생선 뼈처럼main
이라는 하나의 굵은 줄기를 중심으로 짧게 뻗어 나갔다가 다시 합쳐지는feature
브랜치들의 연속으로 보입니다. Git-flow에 비해 훨씬 단순하고 선형적인 그래프가 그려집니다.
항목 | Git-flow | GitHub Flow |
---|---|---|
복잡도 | 높음 (브랜치 종류가 많음) | 낮음 (main + feature ) |
주요 브랜치 | main , develop | main |
배포 주기 | 계획된 릴리즈 (주기적) | 수시로, 지속적으로 |
적합한 프로젝트 | 버전 관리 앱, 대규모 시스템 | 웹 서비스, CI/CD 환경 |
Tig 그래프 모양 | 복잡한 다중 줄기 그래프 | 단순한 단일 줄기(어골형) 그래프 |
보너스 모듈 9: Git 내부 동작 원리 (The Internals)
강좌 목표: Git을 블랙박스가 아닌, 내부 구조가 보이는 화이트박스로 이해합니다. Git의 3대 핵심 객체(Blob, Tree, Commit)의 관계를 파악하고, .git
폴더 안의 파일들이 어떻게 히스토리를 구성하는지 직접 확인하여 Git에 대한 근본적인 이해를 높입니다.
1. .git
폴더: 모든 역사가 담긴 곳
git init
을 실행하면 생기는 .git
폴더가 Git의 본체입니다. 이 안에 프로젝트의 모든 버전, 브랜치, 설정 정보가 들어있습니다.
HEAD
: 현재 내가 작업 중인 브랜치가 무엇인지 가리키는 포인터. (cat .git/HEAD
로 열어보면ref: refs/heads/main
과 같이 나옴)refs/
: 브랜치, 태그 등 모든 '참조' 정보가 담긴 폴더.refs/heads/main
파일 안에는main
브랜치가 가리키는 최신 커밋의 해시값이 들어있습니다.objects/
: Git의 핵심 데이터베이스. 프로젝트의 모든 내용물(파일, 디렉토리 구조, 커밋 정보)이 객체 형태로 압축되어 저장됩니다.
2. Git의 3대 핵심 객체
Git은 모든 것을 3가지 종류의 객체로 저장합니다. 모든 객체는 내용에 따라 고유한 40자리의 SHA-1 해시값을 가집니다.
-
Blob (Binary Large Object): 파일의 내용물 그 자체입니다. 파일 이름이나 생성 날짜 같은 메타데이터는 전혀 없고, 오직 순수한 데이터 덩어리입니다. 같은 내용의 파일은 프로젝트 내에서 단 하나의 Blob 객체만 공유합니다.
-
Tree: 디렉토리 구조를 저장합니다. 특정 시점의 디렉토리에 어떤 파일(Blob)과 하위 디렉토리(다른 Tree)가 있었는지에 대한 목록과 각 항목의 해시값을 가지고 있습니다. 폴더의 스냅샷과 같습니다.
-
Commit: 하나의 스냅샷을 의미하는 가장 중요한 객체입니다. Commit 객체는 다음 정보를 가리키는 포인터를 가지고 있습니다.
- 해당 시점의 최상위 디렉토리 구조 (
tree
객체의 해시) - 이전 커밋(들) (
parent
커밋의 해시) - 작성자, 커밋한 사람, 날짜, 그리고 커밋 메시지
- 해당 시점의 최상위 디렉토리 구조 (
3. git cat-file
로 히스토리 추적하기
git cat-file -p <hash>
명령어는 해당 해시값의 객체 내용을 예쁘게 보여주는 마법 같은 도구입니다. 이것으로 히스토리의 연결고리를 직접 따라가 봅시다.
-
현재 브랜치의 최신 커밋 찾기:
cat .git/refs/heads/main # 4e5f6g7... 와 같은 해시값이 출력됨
-
Commit 객체 내용 보기: 위에서 얻은 해시로 Commit 객체를 열어봅니다.
git cat-file -p 4e5f6g7 # 출력 예시: # tree a1b2c3d... <-- 이 커밋의 파일/디렉토리 구조 # parent 1a2b3c4... <-- 이전 커밋 # author Your Name ... # # Merge branch 'feature/rule-update'
-
Tree 객체 내용 보기: 위에서 찾은
tree
해시로 Tree 객체를 열어봅니다.git cat-file -p a1b2c3d # 출력 예시: # 100644 blob b2c3d4e... README.md # 100644 blob c3d4e5f... team-rules.md
-
Blob 객체 내용 보기: 위에서 찾은
team-rules.md
의blob
해시로 Blob 객체를 열어봅니다.git cat-file -p c3d4e5f # 출력 예시: # # 우리 팀의 규칙 # - 1. 논의 후 자율 출근으로 결정
이 과정을 통해, 브랜치(
refs/heads/main
)는 커밋을, 커밋은 트리와 부모 커밋을, 트리는 블롭을 가리키는 연결 리스트 구조임을 알 수 있습니다.tig
는 바로 이 연결 구조를 읽어서 우리에게 예쁜 그래프로 시각화해주는 것입니다.
최종 요약:
이 보너스 모듈들을 통해 당신은 이제 실전 협업의 난관인 충돌을 자신감 있게 해결하고, 프로젝트의 성격에 맞는 브랜치 전략을 논의할 수 있으며, Git이 내부적으로 어떻게 동작하는지에 대한 깊은 이해까지 갖추게 되었습니다. 진정한 'Git 전문가'의 반열에 오르신 것을 축하합니다