Git 커밋이 다른 커밋의 조상인지 확인하는 방법

GitBeginner
지금 연습하기

소개

이 랩에서는 Git 커밋이 다른 커밋의 조상인지 확인하는 방법을 배우게 됩니다. 커밋 간의 조상 관계를 이해하는 것은 프로젝트의 히스토리를 탐색하고 이해하는 데 매우 중요합니다.

이 목적을 위해 강력한 도구인 git merge-base --is-ancestor 명령어를 살펴볼 것입니다. 또한, 커밋 히스토리를 시각화하고 조상을 추적하기 위해 git log를 활용하고, 조상이 아닌 커밋으로 명령어를 테스트하여 이해도를 높일 것입니다. 이 랩을 마치면 Git 저장소 내에서 조상 관계를 능숙하게 식별할 수 있게 됩니다.

git merge-base --is-ancestor 사용

이 단계에서는 git merge-base --is-ancestor 명령어를 사용하여 한 커밋이 다른 커밋의 조상인지 확인하는 방법을 배우겠습니다. 이는 Git 에서 프로젝트의 서로 다른 버전 간의 히스토리와 관계를 이해하는 데 기본적인 개념입니다.

먼저, 간단한 Git 저장소를 만들고 몇 개의 커밋을 생성하여 히스토리를 구축해 보겠습니다. 아직 해당 디렉토리에 있지 않다면 프로젝트 디렉토리로 이동합니다.

cd ~/project

이제 이 랩을 위한 새 디렉토리를 만들고 그 안에 Git 저장소를 초기화합니다.

mkdir git-ancestor-lab
cd git-ancestor-lab
git init

다음과 유사한 출력을 볼 수 있습니다.

Initialized empty Git repository in /home/labex/project/git-ancestor-lab/.git/

다음으로, 첫 번째 파일을 만들고 커밋해 보겠습니다.

echo "Initial content" > file1.txt
git add file1.txt
git commit -m "Add file1 with initial content"

커밋을 확인하는 출력을 보게 됩니다.

[master (root-commit) <commit-hash>] Add file1 with initial content
 1 file changed, 1 insertion(+)
 create mode 100644 file1.txt

이제 다른 커밋을 만들어 보겠습니다. 파일을 수정하고 변경 사항을 커밋합니다.

echo "More content" >> file1.txt
git add file1.txt
git commit -m "Add more content to file1"

두 번째 커밋을 확인하는 출력을 보게 됩니다.

[master <commit-hash>] Add more content to file1
 1 file changed, 1 insertion(+)

이제 두 개의 커밋이 있는 간단한 히스토리가 있습니다. 로그를 보고 커밋 해시를 확인해 보겠습니다.

git log --oneline

출력은 다음과 유사하게 표시됩니다 (커밋 해시는 다를 것입니다).

<commit-hash-2> (HEAD -> master) Add more content to file1
<commit-hash-1> Add file1 with initial content

이 출력에서 <commit-hash-1>은 첫 번째 커밋의 해시이고, <commit-hash-2>는 두 번째 커밋의 해시입니다. 두 번째 커밋은 첫 번째 커밋의 직접적인 후손입니다. 즉, 첫 번째 커밋은 두 번째 커밋의 조상입니다.

git merge-base --is-ancestor <ancestor-commit> <descendant-commit> 명령어는 첫 번째 커밋이 두 번째 커밋의 조상인지 확인합니다. 조상인 경우, 명령어는 상태 0 (성공) 으로 종료됩니다. 그렇지 않은 경우, 상태 1 (실패) 로 종료됩니다.

이것을 테스트해 보겠습니다. <commit-hash-1><commit-hash-2>git log --oneline 출력에서 얻은 실제 해시로 바꿉니다.

git merge-base --is-ancestor <commit-hash-1> <commit-hash-2>
echo $?

echo $? 명령어는 이전 명령의 종료 상태를 출력합니다. <commit-hash-1><commit-hash-2>의 조상이므로, git merge-base 명령어는 성공해야 하며, echo $?의 출력은 0이어야 합니다.

조상 관계를 이해하는 것은 병합 (merging) 및 리베이스 (rebasing) 와 같은 많은 Git 작업에 매우 중요합니다. 이는 Git 이 서로 다른 브랜치 또는 커밋 간의 공통 히스토리를 결정하는 데 도움이 되기 때문입니다.

git log 실행하여 조상 관계 추적

이 단계에서는 git log 명령어를 사용하여 커밋 히스토리를 시각화하고 조상 (ancestry) 의 개념을 더 명확하게 이해할 것입니다. git log 명령어는 저장소의 히스토리를 탐색하는 강력한 도구입니다.

아직 해당 디렉토리에 있지 않다면 저장소 디렉토리로 이동합니다.

cd ~/project/git-ancestor-lab

저장소에 이미 두 개의 커밋이 있습니다. 이번에는 기본 형식을 사용하여 로그를 다시 살펴보겠습니다.

git log

출력은 커밋 해시, 작성자, 날짜 및 커밋 메시지를 포함하여 각 커밋의 세부 정보를 표시합니다. 커밋은 역 시간 순서 (최신순) 로 나열됩니다.

commit <commit-hash-2> (HEAD -> master)
Author: Jane Doe <jane.doe@example.com>
Date:   <Date and Time>

    Add more content to file1

commit <commit-hash-1>
Author: Jane Doe <jane.doe@example.com>
Date:   <Date and Time>

    Add file1 with initial content

이 출력에서 두 번째 커밋 (<commit-hash-2>) 이 첫 번째 커밋 (<commit-hash-1>) 을 가리키는 것을 볼 수 있습니다. 이것이 Git 이 히스토리를 추적하는 방식입니다. 각 커밋 (초기 커밋 제외) 에는 부모 커밋이 있으며, 이 부모 - 자식 관계가 조상을 정의합니다.

git log 명령어는 기본적으로 현재 커밋 (HEAD -> master로 표시됨) 부터 시작하여 이 부모 체인을 뒤로 이동합니다.

히스토리를 약간 더 길게 만들기 위해 다른 커밋을 추가해 보겠습니다.

echo "Final content" >> file1.txt
git add file1.txt
git commit -m "Add final content to file1"

이제 git log --oneline을 다시 실행하여 업데이트된 히스토리를 확인합니다.

git log --oneline

출력은 세 개의 커밋을 표시합니다.

<commit-hash-3> (HEAD -> master) Add final content to file1
<commit-hash-2> Add more content to file1
<commit-hash-1> Add file1 with initial content

여기서 <commit-hash-3>은 최신 커밋이고, <commit-hash-2>는 부모이며, <commit-hash-1><commit-hash-2>의 부모입니다. 즉, <commit-hash-1><commit-hash-2><commit-hash-3>의 조상입니다. 마찬가지로 <commit-hash-2><commit-hash-3>의 조상입니다.

git merge-base --is-ancestor를 사용하여 이러한 관계를 확인할 수 있습니다. 자리 표시자를 실제 커밋 해시로 바꿉니다.

git merge-base --is-ancestor <commit-hash-1> <commit-hash-3>
echo $?

첫 번째 커밋이 세 번째 커밋의 조상이므로, 이 명령어는 0을 출력해야 합니다.

git merge-base --is-ancestor <commit-hash-2> <commit-hash-3>
echo $?

두 번째 커밋이 세 번째 커밋의 조상이므로, 이 명령어 역시 0을 출력해야 합니다.

git log를 사용하면 커밋 그래프를 시각화하고 부모 - 자식 관계를 이해하는 데 도움이 되며, 이는 git merge-base --is-ancestor가 확인하는 조상 (ancestry) 의 개념과 직접적으로 관련됩니다.

조상이 아닌 커밋 테스트

이전 단계에서는 git merge-base --is-ancestor를 사용하여 이전 커밋이 동일한 브랜치의 이후 커밋의 조상임을 확인했습니다. 이제 서로의 조상이 아닌 커밋을 테스트할 때 어떤 일이 발생하는지 살펴보겠습니다.

저장소 디렉토리로 이동합니다.

cd ~/project/git-ancestor-lab

현재 세 개의 커밋이 있는 단일 브랜치 (master) 가 있습니다. 조상 관계가 아닌 것을 테스트하려면 새 브랜치를 만들고 해당 브랜치에서 커밋을 해야 합니다. 이렇게 하면 분기된 히스토리가 생성됩니다.

먼저, feature라는 새 브랜치를 만들어 보겠습니다.

git branch feature

이 명령어는 feature라는 새 브랜치 포인터를 생성하며, 이는 master동일한 커밋 (최신 커밋, <commit-hash-3>) 을 가리킵니다.

이제 feature 브랜치로 전환해 보겠습니다.

git checkout feature

브랜치가 전환되었음을 나타내는 출력을 보게 됩니다.

Switched to branch 'feature'

이제 feature 브랜치에 있습니다. 이 브랜치에서 새 커밋을 만들어 보겠습니다. 새 파일을 만듭니다.

echo "Feature content" > file2.txt
git add file2.txt
git commit -m "Add file2 on feature branch"

feature 브랜치에서 커밋을 확인하는 출력을 보게 됩니다.

[feature <commit-hash-4>] Add file2 on feature branch
 1 file changed, 1 insertion(+)
 create mode 100644 file2.txt

이제 git log --oneline --all --graph를 사용하여 히스토리를 살펴보겠습니다. --all 플래그는 모든 브랜치의 커밋을 표시하고, --graph는 커밋 히스토리의 텍스트 기반 표현을 그립니다.

git log --oneline --all --graph

출력은 분기된 히스토리를 표시합니다. 다음과 유사하게 표시될 수 있습니다 (커밋 해시는 다를 수 있습니다).

* <commit-hash-4> (HEAD -> feature) Add file2 on feature branch
* <commit-hash-3> (master) Add final content to file1
* <commit-hash-2> Add more content to file1
* <commit-hash-1> Add file1 with initial content

이 그래프에서 <commit-hash-4>feature 브랜치의 최신 커밋이고, <commit-hash-3>master 브랜치의 최신 커밋입니다. 이 두 커밋은 서로의 조상이 아닙니다. 그들은 공통 조상인 <commit-hash-3>(feature 브랜치가 생성된 커밋) 을 공유합니다.

git merge-base --is-ancestor를 사용하여 <commit-hash-4><commit-hash-3> 간의 관계를 테스트해 보겠습니다. 자리 표시자를 실제 커밋 해시로 바꿉니다.

git merge-base --is-ancestor <commit-hash-4> <commit-hash-3>
echo $?

이 명령어는 <commit-hash-4><commit-hash-3>의 조상인지 확인합니다. 그래프를 기반으로, 그렇지 않습니다. 따라서 명령어는 상태 1로 종료되어야 합니다.

이제 반대로 테스트해 보겠습니다. <commit-hash-3><commit-hash-4>의 조상입니까?

git merge-base --is-ancestor <commit-hash-3> <commit-hash-4>
echo $?

이 명령어는 <commit-hash-3><commit-hash-4>의 조상인지 확인합니다. 그래프를 보면, <commit-hash-4>의 부모는 <commit-hash-3>입니다. 따라서 <commit-hash-3><commit-hash-4>조상입니다. 명령어는 상태 0으로 종료되어야 합니다.

이것은 git merge-base --is-ancestor를 사용하여 저장소의 히스토리에서 서로 다른 브랜치 간에도 두 커밋 간의 관계를 프로그래밍 방식으로 확인할 수 있음을 보여줍니다.

요약

이 랩에서는 git merge-base --is-ancestor 명령어를 사용하여 하나의 Git 커밋이 다른 커밋의 조상인지 확인하는 방법을 배웠습니다. 간단한 Git 저장소를 만들고 몇 개의 커밋을 생성하여 히스토리를 설정하는 것으로 시작했습니다. 그런 다음 git log --oneline을 사용하여 커밋 히스토리를 보고 커밋 해시를 식별했습니다. 이 기본적인 단계는 Git 에서 프로젝트의 서로 다른 버전 간의 관계를 이해하는 데 중요합니다.