HOWTO · Git
Git 브랜치 포인터를 다른 커밋으로 이동하는 방법
체크아웃된 Git 브랜치는 git reset으로, 체크아웃되지 않은 다른 브랜치는 git branch -f 또는 git update-ref로 이동합니다. 각 명령이 무엇을 변경하는지와 대상 커밋을 선택하는 방법을 알아봅니다.
이 페이지의 내용
Git 브랜치 포인터를 선택한 커밋으로 이동하려면 해당 브랜치가 체크아웃되어 있을 때 git reset을 사용하세요. 현재 브랜치에 머무르면서 다른 브랜치를 이동하려면 git branch -f 또는 git update-ref를 사용하세요. git branch -f는 어떤 작업 트리에서든 체크아웃된 브랜치의 이동을 거부합니다. git update-ref는 인덱스나 작업 트리를 업데이트하지 않고 참조를 직접 업데이트합니다. 체크아웃된 브랜치에 이를 사용하면 HEAD가 새 커밋을 가리키는 동안 해당 파일들은 이전 커밋에 남아 있을 수 있습니다. 아래의 <target-commit>은 원하는 커밋을 식별하는 커밋 해시, 태그 또는 기타 리비전 식으로 바꾸세요.
체크아웃된 브랜치를 git reset으로 커밋으로 이동하기
git reset은 현재 브랜치를 선택한 커밋으로 이동합니다. 인덱스와 작업 트리에 어떤 일이 일어날지에 따라 모드를 선택하세요. 소프트 리셋은 브랜치를 이동하고 둘 다 그대로 둡니다. 기본 mixed 모드는 브랜치를 이동하고 인덱스를 업데이트하며 작업 트리 파일은 그대로 둡니다. 하드 리셋은 브랜치를 이동하고 인덱스와 추적 중인 작업 트리 파일이 대상 커밋과 일치하게 합니다.
git reset --hard를 사용하기 전에 필요한 추적 중인 변경 사항을 저장하세요. 이 명령은 추적 중인 파일에 대한 커밋되지 않은 변경 사항을 버릴 수 있습니다. 추적되지 않는 파일은 일반적으로 그대로 두지만, 대상 커밋에서 추적 중인 경로를 쓰는 것을 방해하면 Git이 이를 제거하거나 덮어쓸 수 있습니다. 다음의 자체 완결형 예제는 임시 리포지터리를 만들고, main에 두 개의 커밋을 만든 뒤, 체크아웃된 브랜치를 첫 번째 커밋으로 되돌립니다.
set -eu
repo_dir=$(mktemp -d)
trap 'rm -rf "$repo_dir"' EXIT
cd "$repo_dir"
git init -q -b main
git config user.name Example
git config user.email example@example.com
printf 'first version\n' > note.txt
git add note.txt
git commit -q -m first
first_commit=$(git rev-parse HEAD)
printf 'second version\n' > note.txt
git commit -q -am second
git reset --hard "$first_commit" >/dev/null
printf 'Branch: %s\n' "$(git branch --show-current)"
printf 'Commit: %s\n' "$(git log -1 --format=%s)"
Branch: main
Commit: first
자신의 리포지터리에서 이 명령을 적용할 때는 HEAD~1 같은 리비전이나 커밋 해시를 대상으로 사용하세요. 로컬의 추적 중인 변경 사항을 유지해야 한다면 git reset --soft <target-commit> 또는 git reset --mixed <target-commit>을 고려하고, 커밋하기 전에 결과 인덱스와 작업 트리를 검토하세요. 리셋은 현재 브랜치만 변경하며, 다른 브랜치 이름을 직접 이동하지는 않습니다.
체크아웃되지 않은 다른 브랜치를 커밋으로 이동하기
체크아웃된 브랜치가 아닌 다른 브랜치를 이동하려면 대상 브랜치를 현재 작업 트리에서 체크아웃되지 않은 상태로 유지하세요. git branch -f는 명명된 브랜치 참조를 선택한 커밋으로 강제 이동합니다. 예를 들어, git branch -f feature <target-commit>은 feature를 해당 커밋으로 이동합니다. -f는 브랜치의 현재 끝을 의도적으로 교체하므로 사용하기 전에 브랜치 이름과 대상을 확인하세요. 작업 트리에서 체크아웃된 브랜치의 이동은 거부합니다.
git update-ref로 브랜치 참조를 직접 업데이트할 수도 있습니다. 전체 참조 이름과 대상 커밋으로 해석되는 리비전을 사용하세요: git update-ref -m "move feature to target" refs/heads/feature <target-commit>. -m 옵션은 제공된 메시지를 reflog에 기록하여 나중에 참조가 이동한 이유를 설명하는 데 도움이 됩니다. 이 작업에서 feature는 체크아웃되지 않은 다른 브랜치이므로, 두 명령 모두 현재 브랜치를 체크아웃한 상태로 유지하면서 해당 브랜치를 이동합니다. git branch -f와 달리 git update-ref는 체크아웃된 브랜치도 거부하지 않습니다. 참조를 변경하지만 인덱스와 작업 트리 파일은 건드리지 않습니다. 현재 브랜치를 이 방식으로 업데이트하면 HEAD는 새 커밋으로 해석되지만 인덱스와 파일은 여전히 이전 것을 반영하므로, 새 커밋에 대해 변경된 것처럼 보일 수 있습니다.
git checkout -b feature <target-commit>은 새 브랜치를 만들고 체크아웃합니다. 기존 feature 브랜치를 이동하지는 않습니다. 커밋을 직접 체크아웃하면 HEAD가 분리(detached)됩니다. Rebase는 목적이 다릅니다. 커밋을 새 베이스에 다시 재생하고 새 커밋 ID를 만들 수 있으므로, 기존 브랜치를 임의의 커밋으로 지정하는 직접적인 방법이 아닙니다. 체크아웃된 브랜치에는 reset을, 체크아웃되지 않은 다른 브랜치에는 위의 참조 명령 중 하나를 선택하세요.