09. κ³ κΈ Git κΈ°λ²
09. κ³ κΈ Git κΈ°λ²¶
νμ΅ λͺ©ν¶
- Git Hooksλ₯Ό νμ©ν μλν
- Submodulesλ‘ μΈλΆ μμ‘΄μ± κ΄λ¦¬
- Worktreesλ‘ μ¬λ¬ λΈλμΉ λμ μμ
- Git λ΄λΆ ꡬ쑰μ μ μμ€ λͺ λ Ήμ΄ μ΄ν΄
λͺ©μ°¨¶
- Git Hooks
- Git Submodules
- Git Worktrees
- κ³ κΈ λͺ λ Ήμ΄
- Git λ΄λΆ ꡬ쑰
- νΈλ¬λΈμν
- μ°μ΅ λ¬Έμ
1. Git Hooks¶
1.1 Git Hooks κ°μ¶
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Git Hooks μ’
λ₯ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β ν΄λΌμ΄μΈνΈ ν
(λ‘컬): β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β μ»€λ° μν¬νλ‘μ°: β β
β β β’ pre-commit : μ»€λ° μ (λ¦°νΈ, ν
μ€νΈ) β β
β β β’ prepare-commit-msg : μ»€λ° λ©μμ§ μ€λΉ β β
β β β’ commit-msg : μ»€λ° λ©μμ§ κ²μ¦ β β
β β β’ post-commit : μ»€λ° ν β β
β β β β
β β μ΄λ©μΌ μν¬νλ‘μ°: β β
β β β’ applypatch-msg β β
β β β’ pre-applypatch β β
β β β’ post-applypatch β β
β β β β
β β κΈ°ν: β β
β β β’ pre-rebase : rebase μ β β
β β β’ post-checkout : checkout ν β β
β β β’ post-merge : merge ν β β
β β β’ pre-push : push μ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β μλ² ν
(리λͺ¨νΈ): β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β β’ pre-receive : push λ°κΈ° μ β β
β β β’ update : κ° λΈλμΉ μ
λ°μ΄νΈ μ β β
β β β’ post-receive : push λ°μ ν β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
1.2 κΈ°λ³Έ Hook μ€μ ¶
# Hook μμΉ
ls .git/hooks/
# pre-commit.sample, commit-msg.sample, ...
# Hook νμ±ν (μνμμ .sample μ κ±°)
cp .git/hooks/pre-commit.sample .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
# λλ μ§μ μμ±
touch .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
1.3 pre-commit Hook μμ ¶
#!/bin/bash
# .git/hooks/pre-commit
echo "Running pre-commit checks..."
# 1. λ¦°νΈ κ²μ¬
echo "Running ESLint..."
npm run lint
if [ $? -ne 0 ]; then
echo "β ESLint failed. Please fix the errors."
exit 1
fi
# 2. νμ
κ²μ¬
echo "Running TypeScript check..."
npm run type-check
if [ $? -ne 0 ]; then
echo "β TypeScript check failed."
exit 1
fi
# 3. λ¨μ ν
μ€νΈ
echo "Running tests..."
npm test -- --watchAll=false
if [ $? -ne 0 ]; then
echo "β Tests failed."
exit 1
fi
# 4. λ―Όκ° μ 보 κ²μ¬
echo "Checking for secrets..."
if git diff --cached --name-only | xargs grep -l -E "(password|secret|api_key)\s*=" 2>/dev/null; then
echo "β Potential secrets detected!"
exit 1
fi
# 5. νμΌ ν¬κΈ° κ²μ¬
echo "Checking file sizes..."
MAX_SIZE=5242880 # 5MB
for file in $(git diff --cached --name-only); do
if [ -f "$file" ]; then
size=$(wc -c < "$file")
if [ $size -gt $MAX_SIZE ]; then
echo "β File $file is too large ($size bytes)"
exit 1
fi
fi
done
echo "β
All pre-commit checks passed!"
exit 0
1.4 commit-msg Hook μμ ¶
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
# Conventional Commits νμ κ²μ¬
# type(scope): description
PATTERN="^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?: .{1,100}$"
if ! echo "$COMMIT_MSG" | head -1 | grep -qE "$PATTERN"; then
echo "β Invalid commit message format!"
echo ""
echo "Commit message must follow Conventional Commits:"
echo " <type>(<scope>): <description>"
echo ""
echo "Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert"
echo ""
echo "Examples:"
echo " feat(auth): add login functionality"
echo " fix(api): resolve null pointer exception"
echo " docs: update README"
echo ""
exit 1
fi
# λ©μμ§ κΈΈμ΄ κ²μ¬
FIRST_LINE=$(echo "$COMMIT_MSG" | head -1)
if [ ${#FIRST_LINE} -gt 72 ]; then
echo "β First line must be 72 characters or less"
exit 1
fi
echo "β
Commit message is valid!"
exit 0
1.5 pre-push Hook μμ ¶
#!/bin/bash
# .git/hooks/pre-push
REMOTE=$1
URL=$2
# main/master λΈλμΉλ‘ μ§μ push λ°©μ§
PROTECTED_BRANCHES="main master"
CURRENT_BRANCH=$(git symbolic-ref HEAD | sed 's!refs/heads/!!')
for branch in $PROTECTED_BRANCHES; do
if [ "$CURRENT_BRANCH" = "$branch" ]; then
echo "β Direct push to $branch is not allowed!"
echo "Please create a pull request instead."
exit 1
fi
done
# μ 체 ν
μ€νΈ μ€ν
echo "Running full test suite before push..."
npm run test:ci
if [ $? -ne 0 ]; then
echo "β Tests failed. Push aborted."
exit 1
fi
# λΉλ κ²μ¦
echo "Verifying build..."
npm run build
if [ $? -ne 0 ]; then
echo "β Build failed. Push aborted."
exit 1
fi
echo "β
All pre-push checks passed!"
exit 0
1.6 Huskyλ‘ Hook κ΄λ¦¬¶
# Husky μ€μΉ
npm install husky -D
npx husky init
# package.jsonμ prepare μ€ν¬λ¦½νΈ μΆκ°
# "prepare": "husky"
# pre-commit hook μΆκ°
echo "npm run lint && npm test" > .husky/pre-commit
# commit-msg hook μΆκ°
npm install @commitlint/cli @commitlint/config-conventional -D
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
# commitlint.config.js
# module.exports = { extends: ['@commitlint/config-conventional'] };
// lint-staged.config.js
module.exports = {
'*.{js,jsx,ts,tsx}': [
'eslint --fix',
'prettier --write',
'jest --findRelatedTests --passWithNoTests'
],
'*.{json,md,yml,yaml}': [
'prettier --write'
],
'*.css': [
'stylelint --fix',
'prettier --write'
]
};
2. Git Submodules¶
2.1 Submodules κ°μ¶
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Git Submodules β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β λ©μΈ μ μ₯μ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β my-project/ β β
β β βββ src/ β β
β β βββ tests/ β β
β β βββ .gitmodules β μλΈλͺ¨λ μ€μ β β
β β βββ libs/ β β
β β βββ shared-ui/ β μλΈλͺ¨λ (μΈλΆ μ μ₯μ) β β
β β βββ common-utils/β μλΈλͺ¨λ (μΈλΆ μ μ₯μ) β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β νΉμ§: β
β β’ μΈλΆ μ μ₯μλ₯Ό νμ λλ ν λ¦¬λ‘ ν¬ν¨ β
β β’ νΉμ 컀λ°μ κ³ μ λ¨ β
β β’ λ
립μ μΈ λ²μ κ΄λ¦¬ β
β ⒠곡μ λΌμ΄λΈλ¬λ¦¬, μμ‘΄μ± κ΄λ¦¬μ μ μ© β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2.2 Submodule κΈ°λ³Έ λͺ λ Ή¶
# μλΈλͺ¨λ μΆκ°
git submodule add https://github.com/example/shared-ui.git libs/shared-ui
# .gitmodules νμΌ μμ±λ¨
# [submodule "libs/shared-ui"]
# path = libs/shared-ui
# url = https://github.com/example/shared-ui.git
# νΉμ λΈλμΉ μΆμ
git submodule add -b develop https://github.com/example/lib.git libs/lib
# μλΈλͺ¨λμ΄ μλ μ μ₯μ ν΄λ‘
git clone --recursive https://github.com/example/main-project.git
# λλ ν΄λ‘ ν μ΄κΈ°ν
git clone https://github.com/example/main-project.git
git submodule init
git submodule update
# λλ ν λ²μ
git submodule update --init --recursive
2.3 Submodule μ λ°μ΄νΈ¶
# μλΈλͺ¨λ μ
λ°μ΄νΈ (μ€μ λ 컀λ°μΌλ‘)
git submodule update
# μλΈλͺ¨λμ μ΅μ μΌλ‘ μ
λ°μ΄νΈ
git submodule update --remote
# νΉμ μλΈλͺ¨λλ§ μ
λ°μ΄νΈ
git submodule update --remote libs/shared-ui
# λͺ¨λ μλΈλͺ¨λμμ λͺ
λ Ή μ€ν
git submodule foreach 'git checkout main && git pull'
# μλΈλͺ¨λ μν νμΈ
git submodule status
# -abc1234 libs/shared-ui (v1.0.0) β - λ μ΄κΈ°ν μ λ¨
# +def5678 libs/common-utils (heads/main) β + λ λ€λ₯Έ 컀λ°
# λ³κ²½μ¬ν 컀λ°
cd libs/shared-ui
git checkout main
git pull
cd ../..
git add libs/shared-ui
git commit -m "Update shared-ui submodule"
2.4 Submodule μ κ±°¶
# 1. .gitmodulesμμ νλͺ© μ κ±°
git config -f .gitmodules --remove-section submodule.libs/shared-ui
# 2. .git/configμμ νλͺ© μ κ±°
git config --remove-section submodule.libs/shared-ui
# 3. μ€ν
μ΄μ§μμ μ κ±°
git rm --cached libs/shared-ui
# 4. .git/modulesμμ μ κ±°
rm -rf .git/modules/libs/shared-ui
# 5. μμ
λλ ν 리μμ μ κ±°
rm -rf libs/shared-ui
# 6. 컀λ°
git commit -m "Remove shared-ui submodule"
2.5 Submodule μ£Όμμ¬ν¶
# β οΈ μλΈλͺ¨λ λ΄μμ λΈλμΉ νμΈ
cd libs/shared-ui
git branch
# * (HEAD detached at abc1234) β Detached HEAD!
# μλΈλͺ¨λμμ μμ
νλ €λ©΄ λΈλμΉλ‘ 체ν¬μμ
git checkout main
# μ΄μ λ³κ²½ κ°λ₯
# β οΈ Pull μ μλΈλͺ¨λ μλ μ
λ°μ΄νΈ
git pull --recurse-submodules
# λλ μ€μ
git config --global submodule.recurse true
# β οΈ μλΈλͺ¨λ λ³κ²½ ν λ©μΈ μ μ₯μμμ μ»€λ° νμ
git status
# modified: libs/shared-ui (new commits)
git add libs/shared-ui
git commit -m "Update shared-ui to latest"
3. Git Worktrees¶
3.1 Worktrees κ°μ¶
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Git Worktrees β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β νλμ μ μ₯μ, μ¬λ¬ μμ
λλ ν 리 β
β β
β ~/.git/my-project/ β λ©μΈ μ μ₯μ β
β βββ .git/ β
β βββ src/ β
β βββ (νμ¬ λΈλμΉ: main) β
β β
β ~/worktrees/feature-a/ β Worktree 1 β
β βββ .git (νμΌ, λ©μΈ .git μ°Έμ‘°) β
β βββ src/ β
β βββ (νμ¬ λΈλμΉ: feature/a) β
β β
β ~/worktrees/hotfix/ β Worktree 2 β
β βββ .git (νμΌ, λ©μΈ .git μ°Έμ‘°) β
β βββ src/ β
β βββ (νμ¬ λΈλμΉ: hotfix/urgent) β
β β
β μ₯μ : β
β β’ stash μμ΄ λΈλμΉ μ ν β
β β’ μ¬λ¬ λΈλμΉ λμ μμ
β
β β’ κΈ΄ λΉλ μ€ λ€λ₯Έ μμ
κ°λ₯ β
β β’ CIμμ μ¬λ¬ λΈλμΉ λ³λ ¬ λΉλ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
3.2 Worktree λͺ λ Ήμ΄¶
# Worktree λͺ©λ‘ νμΈ
git worktree list
# /home/user/my-project abc1234 [main]
# μ Worktree μΆκ° (κΈ°μ‘΄ λΈλμΉ)
git worktree add ../feature-a feature/a
# Preparing worktree (checking out 'feature/a')
# μ Worktree μΆκ° (μ λΈλμΉ μμ±)
git worktree add -b feature/b ../feature-b main
# νΉμ κ²½λ‘μ μΆκ°
git worktree add ~/worktrees/hotfix hotfix/urgent
# Worktree λͺ©λ‘ νμΈ
git worktree list
# /home/user/my-project abc1234 [main]
# /home/user/feature-a def5678 [feature/a]
# /home/user/worktrees/hotfix ghi9012 [hotfix/urgent]
# Worktreeμμ μμ
cd ../feature-a
# μΌλ°μ μΈ Git μμ
μν
git add .
git commit -m "Work on feature A"
git push
# Worktree μ κ±°
git worktree remove ../feature-a
# λλ λλ ν 리 μμ ν μ 리
rm -rf ../feature-a
git worktree prune # μ ν¨νμ§ μμ worktree μ 리
# μ κΈ/μ κΈ ν΄μ (μ€μλ‘ μμ λ°©μ§)
git worktree lock ../feature-a
git worktree unlock ../feature-a
3.3 Worktree νμ© μ¬λ‘¶
# μ¬λ‘ 1: κΈ΄κΈ λ²κ·Έ μμ
# νμ¬ feature μμ
μ€μΈλ° κΈ΄κΈ λ²κ·Έ λ°μ
git worktree add ../hotfix main
cd ../hotfix
git checkout -b hotfix/critical-bug
# λ²κ·Έ μμ
git add . && git commit -m "Fix critical bug"
git push -u origin hotfix/critical-bug
# PR μμ± ν λ³ν©
cd ../my-project
git worktree remove ../hotfix
# μ¬λ‘ 2: μ½λ 리뷰
# PR μ½λλ₯Ό λ‘컬μμ νμΈ
git fetch origin
git worktree add ../pr-123 origin/feature/new-feature
cd ../pr-123
npm install && npm test
# 리뷰 ν μ κ±°
git worktree remove ../pr-123
# μ¬λ‘ 3: λ³λ ¬ λΉλ (CI)
git worktree add ../build-debug main
git worktree add ../build-release main
cd ../build-debug && npm run build:debug &
cd ../build-release && npm run build:release &
wait
# μ¬λ‘ 4: λ²μ λΉκ΅
git worktree add ../v1.0 v1.0.0
git worktree add ../v2.0 v2.0.0
diff -r ../v1.0/src ../v2.0/src
4. κ³ κΈ λͺ λ Ήμ΄¶
4.1 Git Bisect (μ΄μ§ κ²μ)¶
# λ²κ·Έκ° λ°μν μ»€λ° μ°ΎκΈ°
git bisect start
# νμ¬ μν (λ²κ·Έ μμ)
git bisect bad
# μ μμ΄μλ 컀λ°
git bisect good abc1234
# Gitμ΄ μ€κ° 컀λ°μΌλ‘ 체ν¬μμ
# ν
μ€νΈ ν κ²°κ³Ό νμ
git bisect good # λλ git bisect bad
# λ°λ³΅...
# κ²°κ³Ό:
# abc1234 is the first bad commit
# μ’
λ£
git bisect reset
# μλνλ bisect
git bisect start HEAD abc1234
git bisect run npm test
# μλμΌλ‘ good/bad νλ¨νμ¬ μ°Ύμ
4.2 Git Reflog¶
# λͺ¨λ HEAD μ΄λ κΈ°λ‘
git reflog
# abc1234 HEAD@{0}: commit: Add feature
# def5678 HEAD@{1}: checkout: moving from main to feature
# ghi9012 HEAD@{2}: reset: moving to HEAD~1
# ...
# νΉμ λΈλμΉμ reflog
git reflog show main
# μμ λ μ»€λ° λ³΅κ΅¬
git reflog
# abc1234 HEAD@{5}: commit: Important work β μ΄ μ»€λ° λ³΅κ΅¬
git checkout abc1234
git checkout -b recovered-branch
# μλͺ»λ reset μ·¨μ
git reset --hard HEAD@{2}
# reflog λ§λ£ κΈ°κ° (κΈ°λ³Έ 90μΌ)
git config gc.reflogExpire 180.days
4.3 Git Stash κ³ κΈ¶
# κΈ°λ³Έ stash
git stash
git stash push -m "Work in progress on feature X"
# νΉμ νμΌλ§ stash
git stash push -m "Partial work" -- src/file1.js src/file2.js
# Untracked νμΌ ν¬ν¨
git stash push -u -m "Include untracked"
# λͺ¨λ νμΌ ν¬ν¨ (ignored ν¬ν¨)
git stash push -a -m "Include all"
# Stash λͺ©λ‘
git stash list
# stash@{0}: On feature: Work in progress
# stash@{1}: On main: Bug fix attempt
# νΉμ stash μ μ© (μμ μ ν¨)
git stash apply stash@{1}
# νΉμ stash μ μ© ν μμ
git stash pop stash@{1}
# Stash λ΄μ© νμΈ
git stash show -p stash@{0}
# Stashλ₯Ό λΈλμΉλ‘ λ³ν
git stash branch new-feature stash@{0}
# Stash μμ
git stash drop stash@{0}
git stash clear # λͺ¨λ μμ
4.4 Git Cherry-pick κ³ κΈ¶
# κΈ°λ³Έ cherry-pick
git cherry-pick abc1234
# μ¬λ¬ 컀λ°
git cherry-pick abc1234 def5678 ghi9012
# λ²μ cherry-pick
git cherry-pick abc1234..ghi9012 # abc1234 μ μΈ
git cherry-pick abc1234^..ghi9012 # abc1234 ν¬ν¨
# 컀λ°νμ§ μκ³ λ³κ²½λ§ μ μ©
git cherry-pick -n abc1234
# μΆ©λ ν΄κ²° ν κ³μ
git cherry-pick --continue
# μ€λ¨
git cherry-pick --abort
# Merge μ»€λ° cherry-pick (-m μ΅μ
νμ)
git cherry-pick -m 1 abc1234
# -m 1: 첫 λ²μ§Έ λΆλͺ¨ κΈ°μ€ (λ³΄ν΅ main)
# -m 2: λ λ²μ§Έ λΆλͺ¨ κΈ°μ€ (λ³ν©λ λΈλμΉ)
4.5 Git Rebase κ³ κΈ¶
# λνν rebase
git rebase -i HEAD~5
# pick, reword, edit, squash, fixup, drop
# νΉμ 컀λ°λΆν° rebase
git rebase -i abc1234
# Autosquash (fixup! μ λμ¬ μλ μ²λ¦¬)
git commit --fixup abc1234
git rebase -i --autosquash abc1234^
# Rebase μ€ μΆ©λ
git rebase --continue
git rebase --skip
git rebase --abort
# onto μ΅μ
(λΈλμΉ μ΄λ)
git rebase --onto main feature-base feature
# feature-baseμ feature μ¬μ΄μ 컀λ°μ main μλ‘ μ΄λ
# preserve-merges (λ³ν© μ»€λ° μ μ§) - deprecated
git rebase --rebase-merges main
5. Git λ΄λΆ ꡬ쑰¶
5.1 Git κ°μ²΄¶
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Git κ°μ²΄ μ ν β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β Blob (νμΌ λ΄μ©) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β SHA-1: abc123... β β
β β λ΄μ©: (νμΌμ λ°μ΄λ리 λ°μ΄ν°) β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Tree (λλ ν 리) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β SHA-1: def456... β β
β β 100644 blob abc123... README.md β β
β β 100644 blob bcd234... main.js β β
β β 040000 tree cde345... src β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Commit (컀λ°) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β SHA-1: ghi789... β β
β β tree def456... β β
β β parent efg567... β β
β β author John <john@example.com> 1234567890 +0900 β β
β β committer John <john@example.com> 1234567890 +0900β β
β β β β
β β Commit message β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β Tag (νκ·Έ - annotated) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β SHA-1: jkl012... β β
β β object ghi789... (컀λ°) β β
β β type commit β β
β β tag v1.0.0 β β
β β tagger John <john@example.com> 1234567890 +0900 β β
β β β β
β β Release version 1.0.0 β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
5.2 μ μμ€ λͺ λ Ήμ΄ (Plumbing)¶
# κ°μ²΄ νμ
νμΈ
git cat-file -t abc1234
# commit
# κ°μ²΄ λ΄μ© νμΈ
git cat-file -p abc1234
# tree def456789...
# parent ...
# author ...
# νμ¬ μ»€λ°μ tree νμΈ
git cat-file -p HEAD^{tree}
# Blob λ΄μ© νμΈ
git cat-file -p abc1234:README.md
# κ°μ²΄ ν΄μ κ³μ°
echo "Hello" | git hash-object --stdin
# λλ νμΌλ‘
git hash-object README.md
# κ°μ²΄ μ μ₯
echo "Hello" | git hash-object -w --stdin
# Tree μμ±
git write-tree
# μ»€λ° μμ±
echo "Commit message" | git commit-tree <tree-sha> -p <parent-sha>
# λ νΌλ°μ€ μ
λ°μ΄νΈ
git update-ref refs/heads/new-branch abc1234
5.3 Git λλ ν 리 ꡬ쑰¶
.git/
βββ HEAD # νμ¬ λΈλμΉ μ°Έμ‘°
βββ config # μ μ₯μ μ€μ
βββ description # GitWeb μ€λͺ
βββ hooks/ # Git hooks
βββ info/
β βββ exclude # λ‘컬 .gitignore
βββ objects/ # λͺ¨λ κ°μ²΄ μ μ₯
β βββ pack/ # μμΆλ κ°μ²΄
β βββ info/
β βββ ab/
β βββ c123... # κ°μ²΄ νμΌ (μ²μ 2μκ° λλ ν 리)
βββ refs/
β βββ heads/ # λ‘컬 λΈλμΉ
β β βββ main
β βββ remotes/ # μ격 λΈλμΉ
β β βββ origin/
β β βββ main
β βββ tags/ # νκ·Έ
β βββ v1.0.0
βββ logs/ # reflog μ μ₯
β βββ HEAD
β βββ refs/
βββ index # μ€ν
μ΄μ§ μμ
βββ COMMIT_EDITMSG # λ§μ§λ§ μ»€λ° λ©μμ§
6. νΈλ¬λΈμν ¶
6.1 μΌλ°μ μΈ λ¬Έμ ν΄κ²°¶
# λ§μ§λ§ μ»€λ° μμ (push μ )
git commit --amend -m "New message"
git commit --amend --no-edit # λ©μμ§ μ μ§
# Pushλ μ»€λ° μμ (μν!)
git commit --amend
git push --force-with-lease # μμ ν force push
# μλͺ»λ λΈλμΉμ μ»€λ° (push μ )
git branch correct-branch # νμ¬ μ»€λ°μΌλ‘ μ λΈλμΉ
git reset --hard HEAD~1 # νμ¬ λΈλμΉ λλ리기
git checkout correct-branch # μ¬λ°λ₯Έ λΈλμΉλ‘ μ΄λ
# 컀λ°μμ νμΌ μ κ±°
git reset HEAD~ -- file.txt
git commit --amend
# λ―Όκ° μ 보 μ κ±° (λͺ¨λ νμ€ν 리μμ)
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch secrets.txt" \
--prune-empty --tag-name-filter cat -- --all
# λλ BFG Repo-Cleaner μ¬μ© (λ λΉ λ¦)
bfg --delete-files secrets.txt
bfg --replace-text passwords.txt
6.2 μΆ©λ ν΄κ²°¶
# Merge μΆ©λ νμΈ
git status
git diff --name-only --diff-filter=U
# μΆ©λ λ§μ»€
# <<<<<<< HEAD
# νμ¬ λΈλμΉ λ΄μ©
# =======
# λ³ν©νλ €λ λΈλμΉ λ΄μ©
# >>>>>>> feature
# νμΌλ³λ‘ μ ν
git checkout --ours file.txt # νμ¬ λΈλμΉ μ ν
git checkout --theirs file.txt # λ³ν© λΈλμΉ μ ν
# Merge λꡬ μ¬μ©
git mergetool
# μΆ©λ ν΄κ²° ν
git add file.txt
git commit
# Merge μ€λ¨
git merge --abort
6.3 λμ©λ μ μ₯μ κ΄λ¦¬¶
# ν° νμΌ μ°ΎκΈ°
git rev-list --objects --all | \
git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' | \
sed -n 's/^blob //p' | \
sort -nk2 | \
tail -20
# Git LFS μ€μ
git lfs install
git lfs track "*.psd"
git lfs track "*.zip"
git add .gitattributes
git add large-file.psd
git commit -m "Add large file with LFS"
# μ μ₯μ ν¬κΈ° μ€μ΄κΈ°
git gc --aggressive --prune=now
git repack -a -d --depth=250 --window=250
# Shallow clone
git clone --depth 1 https://github.com/repo.git
# Sparse checkout
git sparse-checkout init
git sparse-checkout set src/ tests/
7. μ°μ΅ λ¬Έμ ¶
μ°μ΅ 1: Git Hooks μ€μ ¶
# μꡬμ¬ν:
# 1. pre-commit: μ½λ ν¬λ§·ν
κ²μ¬
# 2. commit-msg: Conventional Commits κ²μ¦
# 3. pre-push: ν
μ€νΈ μ€ν
# 4. Huskyλ‘ νκ³Ό 곡μ κ°λ₯νκ² μ€μ
# Hook μ€ν¬λ¦½νΈ μμ±:
μ°μ΅ 2: Submodule νλ‘μ νΈ¶
# μꡬμ¬ν:
# 1. λ©μΈ νλ‘μ νΈ μμ±
# 2. 곡μ λΌμ΄λΈλ¬λ¦¬λ₯Ό submoduleλ‘ μΆκ°
# 3. Submodule μ
λ°μ΄νΈ μ€ν¬λ¦½νΈ μμ±
# 4. CIμμ submodule ν¬ν¨ λΉλ
# λͺ
λ Ήμ΄ λ° μ€ν¬λ¦½νΈ μμ±:
μ°μ΅ 3: Worktree νμ©¶
# μꡬμ¬ν:
# 1. λ©μΈ μμ
μ€ κΈ΄κΈ λ²κ·Έ μμ μλ리μ€
# 2. Worktreeλ‘ λ³λ ¬ μμ
# 3. μμ
μλ£ ν μ 리
# λͺ
λ Ήμ΄ μμ±:
μ°μ΅ 4: Bisectλ‘ λ²κ·Έ μ°ΎκΈ°¶
# μꡬμ¬ν:
# 1. ν
μ€νΈ μ€ν¬λ¦½νΈ μμ±
# 2. git bisect runμΌλ‘ μλν
# 3. λ²κ·Έ μ»€λ° μ°ΎκΈ°
# λͺ
λ Ήμ΄ μμ±:
λ€μ λ¨κ³¶
- 10_λͺ¨λ Έλ ν¬_κ΄λ¦¬ - λκ·λͺ¨ μ μ₯μ κ΄λ¦¬
- 08_Git_μν¬νλ‘μ°_μ λ΅ - μν¬νλ‘μ° λ³΅μ΅
- Pro Git Book - μ¬ν νμ΅
μ°Έκ³ μλ£¶
β μ΄μ : Git μν¬νλ‘μ° μ λ΅ | λ€μ: λͺ¨λ Έλ ν¬ κ΄λ¦¬ β | λͺ©μ°¨