Introdução
Neste laboratório, você aprenderá como determinar se um commit Git é um ancestral de outro. Compreender as relações ancestrais entre commits é crucial para navegar e compreender o histórico do seu projeto.
Exploraremos o comando git merge-base --is-ancestor, uma ferramenta poderosa para este propósito. Adicionalmente, utilizaremos o git log para visualizar o histórico de commits e rastrear a ancestralidade, e testaremos o comando com commits não ancestrais para solidificar sua compreensão. Ao final deste laboratório, você estará proficiente em identificar relações ancestrais dentro do seu repositório Git.
Usar git merge-base --is-ancestor
Nesta etapa, aprenderemos como usar o comando git merge-base --is-ancestor para determinar se um commit é um ancestral de outro. Este é um conceito fundamental para entender o histórico e as relações entre diferentes versões do seu projeto no Git.
Primeiramente, vamos criar um repositório Git simples e fazer alguns commits para estabelecer um histórico. Navegue até o diretório do seu projeto, caso ainda não esteja lá:
cd ~/project
Agora, crie um novo diretório para este laboratório e inicialize um repositório Git dentro dele:
mkdir git-ancestor-lab
cd git-ancestor-lab
git init
Você deve ver uma saída semelhante a esta:
Initialized empty Git repository in /home/labex/project/git-ancestor-lab/.git/
Em seguida, vamos criar nosso primeiro arquivo e fazer o commit:
echo "Initial content" > file1.txt
git add file1.txt
git commit -m "Add file1 with initial content"
Você verá uma saída confirmando o commit:
[master (root-commit) <commit-hash>] Add file1 with initial content
1 file changed, 1 insertion(+)
create mode 100644 file1.txt
Agora, vamos fazer outro commit. Modifique o arquivo e faça o commit das alterações:
echo "More content" >> file1.txt
git add file1.txt
git commit -m "Add more content to file1"
Você verá uma saída confirmando o segundo commit:
[master <commit-hash>] Add more content to file1
1 file changed, 1 insertion(+)
Agora temos um histórico simples com dois commits. Vamos visualizar o log para ver os hashes dos commits:
git log --oneline
A saída será algo parecido com isto (seus hashes de commit serão diferentes):
<commit-hash-2> (HEAD -> master) Add more content to file1
<commit-hash-1> Add file1 with initial content
Nesta saída, <commit-hash-1> é o hash do primeiro commit, e <commit-hash-2> é o hash do segundo commit. O segundo commit é um descendente direto do primeiro commit. Isso significa que o primeiro commit é um ancestral do segundo commit.
O comando git merge-base --is-ancestor <ancestor-commit> <descendant-commit> verifica se o primeiro commit é um ancestral do segundo commit. Se for, o comando sai com um status de 0 (sucesso). Se não for, ele sai com um status de 1 (falha).
Vamos testar isso. Substitua <commit-hash-1> e <commit-hash-2> pelos hashes reais da sua saída git log --oneline.
git merge-base --is-ancestor <commit-hash-1> <commit-hash-2>
echo $?
O comando echo $? imprime o status de saída do comando anterior. Como <commit-hash-1> é um ancestral de <commit-hash-2>, o comando git merge-base deve ter sucesso, e a saída de echo $? deve ser 0.
Compreender a ancestralidade é crucial para muitas operações Git, como merging (fusão) e rebasing (rebase), pois ajuda o Git a determinar o histórico comum entre diferentes branches (ramificações) ou commits.
Executar git log para Rastrear a Ancestralidade
Nesta etapa, usaremos o comando git log para visualizar o histórico de commits e entender o conceito de ancestralidade de forma mais clara. O comando git log é uma ferramenta poderosa para explorar o histórico do seu repositório.
Navegue até o diretório do seu repositório, caso ainda não esteja lá:
cd ~/project/git-ancestor-lab
Já temos dois commits em nosso repositório. Vamos visualizar o log novamente, desta vez usando o formato padrão:
git log
A saída mostrará os detalhes de cada commit, incluindo o hash do commit, autor, data e mensagem do commit. Os commits são listados em ordem cronológica inversa (do mais recente para o mais antigo).
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
Nesta saída, você pode ver que o segundo commit (<commit-hash-2>) aponta para o primeiro commit (<commit-hash-1>). É assim que o Git rastreia o histórico. Cada commit (exceto o inicial) tem um commit pai, e essa relação pai-filho define a ancestralidade.
O comando git log essencialmente percorre para trás através desta cadeia de pais, começando pelo commit atual (indicado por HEAD -> master).
Vamos adicionar outro commit para tornar o histórico um pouco mais longo:
echo "Final content" >> file1.txt
git add file1.txt
git commit -m "Add final content to file1"
Agora, execute git log --oneline novamente para ver o histórico atualizado:
git log --oneline
A saída mostrará três commits:
<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
Aqui, <commit-hash-3> é o commit mais recente, <commit-hash-2> é seu pai, e <commit-hash-1> é o pai de <commit-hash-2>. Isso significa que <commit-hash-1> é um ancestral de <commit-hash-2> e <commit-hash-3>. Da mesma forma, <commit-hash-2> é um ancestral de <commit-hash-3>.
Podemos usar git merge-base --is-ancestor para verificar essas relações. Substitua os espaços reservados pelos seus hashes de commit reais.
git merge-base --is-ancestor <commit-hash-1> <commit-hash-3>
echo $?
Isso deve gerar 0 porque o primeiro commit é um ancestral do terceiro commit.
git merge-base --is-ancestor <commit-hash-2> <commit-hash-3>
echo $?
Isso também deve gerar 0 porque o segundo commit é um ancestral do terceiro commit.
Usar git log ajuda você a visualizar o gráfico de commits e entender as relações pai-filho, que se relaciona diretamente com o conceito de ancestralidade que git merge-base --is-ancestor verifica.
Testar Commits Não Ancestrais
Nas etapas anteriores, usamos git merge-base --is-ancestor para confirmar que commits anteriores eram ancestrais de commits posteriores na mesma branch. Agora, vamos explorar o que acontece quando testamos commits que não são ancestrais um do outro.
Navegue até o diretório do seu repositório:
cd ~/project/git-ancestor-lab
Atualmente, temos uma única branch (master) com três commits. Para testar relações não-ancestrais, precisamos criar uma nova branch e fazer um commit nessa branch. Isso criará um histórico divergente.
Primeiro, vamos criar uma nova branch chamada feature:
git branch feature
Este comando cria um novo ponteiro de branch chamado feature que aponta para o mesmo commit que master (nosso último commit, <commit-hash-3>).
Agora, vamos mudar para a branch feature:
git checkout feature
Você deve ver uma saída indicando que você mudou de branch:
Switched to branch 'feature'
Agora estamos na branch feature. Vamos fazer um novo commit nesta branch. Crie um novo arquivo:
echo "Feature content" > file2.txt
git add file2.txt
git commit -m "Add file2 on feature branch"
Você verá uma saída confirmando o commit na branch feature:
[feature <commit-hash-4>] Add file2 on feature branch
1 file changed, 1 insertion(+)
create mode 100644 file2.txt
Agora, vamos olhar para o histórico usando git log --oneline --all --graph. A flag --all mostra commits de todas as branches, e --graph desenha uma representação baseada em texto do histórico de commits.
git log --oneline --all --graph
A saída mostrará um histórico de ramificação. Pode parecer algo assim (os hashes de commit variarão):
* <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
Neste gráfico, <commit-hash-4> é o commit mais recente na branch feature, e <commit-hash-3> é o commit mais recente na branch master. Esses dois commits não são ancestrais um do outro. Eles compartilham um ancestral comum, que é <commit-hash-3> (o commit onde a branch feature foi criada).
Vamos usar git merge-base --is-ancestor para testar a relação entre <commit-hash-4> e <commit-hash-3>. Substitua os espaços reservados pelos seus hashes de commit reais.
git merge-base --is-ancestor <commit-hash-4> <commit-hash-3>
echo $?
Este comando verifica se <commit-hash-4> é um ancestral de <commit-hash-3>. Com base em nosso gráfico, não é. Portanto, o comando deve sair com um status de 1.
Agora, vamos testar o outro lado: <commit-hash-3> é um ancestral de <commit-hash-4>?
git merge-base --is-ancestor <commit-hash-3> <commit-hash-4>
echo $?
Este comando verifica se <commit-hash-3> é um ancestral de <commit-hash-4>. Olhando para o gráfico, o pai de <commit-hash-4> é <commit-hash-3>. Então, <commit-hash-3> é um ancestral de <commit-hash-4>. O comando deve sair com um status de 0.
Isso demonstra como git merge-base --is-ancestor pode ser usado para verificar programaticamente a relação entre quaisquer dois commits no histórico do seu repositório, mesmo em diferentes branches.
Resumo
Neste laboratório, aprendemos como usar o comando git merge-base --is-ancestor para verificar se um commit Git é um ancestral de outro. Começamos criando um repositório Git simples e fazendo alguns commits para estabelecer um histórico. Em seguida, usamos git log --oneline para visualizar o histórico de commits e identificar os hashes dos commits. Esta etapa fundamental é crucial para entender as relações entre diferentes versões de um projeto no Git.



