1. Introdução: O hello world do Git
Este livro é um tutorial que apresenta uma forma muito simples de se usar o Git. Como exemplo, são feitas algumas versões do clássico programa "hello world". Essas versões serão gerenciadas pelo sistema controlador de versões Git. A intenção é mostrar uma forma de se começar a usar o Git dentro de poucos minutos. É apenas um primeiro contato com a ferramenta. Nenhum conteúdo é abordado por completo ou com profundidade. Para isso, são sugeridas obras como [hodson2014ry] e [chacon2014pro].
Mesmo assim, é bom deixar claro que Git é um sistema de gerenciamento de versões de software. Porém, apesar de ter sido idealizado para o desenvolvimento de programas, também pode ser usado para outras finalidades como escrita compartilhada de textos ou qualquer outro tipo de arquivo, até mesmo arquivos de imagens. O Git mantém um histórico das alterações de um repositório permitindo recuperar informações, dividir as tarefas em ramos e mesclar alterações que podem ser feitas independentemente.
1.1. Por que usar Git?
Quem nunca fez uma cópia de um arquivo que desejava alterar (só pra garantir)? Fazemos isso tanto para um código de programa quanto para algum outro tipo documento. O Git mantém essas cópias de forma mais eficiente e organizada. Com o Git, uma equipe consegue trabalhar em diferentes funcionalidades simultaneamente. As cópias só guardam o que foi alterado de uma versão do documento para a outra. Por isso é mais eficiente. O Git te ajuda mesmo que você esteja trabalhando sozinho.
Pessoalmente, várias vezes eu testei alguma alteração em um programa que estava desenvolvendo, e algumas vezes essa alteração saiu muito errada. Não precisei me desesperar. Simplesmente descartei todas as alterações e o programa voltou a funcionar como antes. Mas nem sempre foi assim. Eu mesmo já usei o Git como um simples cliente para enviar e fazer o download do meu código no GitHub como se fosse apenas um backup. Muitas vezes eu precisei excluir o repositório local e baixá-lo novamente. Fiz isso por que eu não conhecia nem os comandos básicos do Git. Espero que você, após ler este livro, não precise cometer os mesmos erros que eu cometi.
1.2. Qual a diferença entre Git e GitHub?
Como já mencionado, Git é um programa que gerencia as versões de arquivos com código fonte de programas e outros documentos. O GitHub é uma plataforma de hospedagem de código que, como o nome já deixa claro, usa o Git como interface de interação. É uma das plataformas mais usadas e famosas. Porém, existem outras como Bitbucket e Gitlab. Neste livro, os exemplos com repositórios remotos serão com o Github. Mas os conceitos são os mesmos para qualquer plataforma de hospedagem que use o Git como interface de interação. O que muda entre as plataformas de hospedagem de código são alguns detalhes da interface web de cada serviço. Também muda o que cada plataforma oferece para seus usuários. Por exemplo, duas ferramentas que eu acho muito úteis no GitHub é o GitHub Pages e o GitHub Actions. Minha página pessoal é hospedada no GitHub pages. Estou usando o GitHub Actions para renderizar este livro toda vez que faço uma atualização no servidor. Acredito que, caso você tenha interesse em usar uma plataforma de hospedagem de código, as informações contidas aqui serão suficientes para você escolher a plataforma que se adequa melhor às suas necessidades.
1.3. Como ler este livro?
Este livro foi pensado para quem nunca teve contato com o Git e nem sabe direito o que ele é. Mas se você já tem uma noção, ou já usou o Git de alguma forma, a figura 1 mostra uma sugestão de como ler este livro.
O capítulo 2 (Iniciando um repositório local) mostra como criar um repositório no seu computador a partir de um diretório. Como criar um repositório no GitHub e utilizá-lo no seu computador é mostrado no capítulo 3 (Repositório remoto no GitHub). No capítulo 4 (Criando fotografias novas e acessando fotografias antigas) é mostrado como criar versões e acessar versões anteriores. Veremos como trabalhar simultaneamente com versões diferentes de um programa no capítulo 5 (Ramos no projeto). Você verá o mínimo necessário para mesclar bifurcações no capítulo 6 (Criando bifurcações no projeto). O capítulo 7 (Conclusão) reforça o que foi mostrado nos demais capítulos e sugere obras para você continuar seu aprendizado.
Neste livro, tudo será apresentado pela linha de comando. O mais importante é entender os conceitos e o motivo de se usar cada comando. Sem estes conceitos uma interface gráfica é inútil. Por isso, acredito que pela linha de comando você entenderá o necessário para usar uma interface gráfica posteriormente. Além disso, os comandos de terminal são os mesmos para Windows, Linux e Mac. Você encontra como instalar o Git em seu computador no endereço Instalando o Git (https://git-scm.com/book/pt-br/v2).
2. Iniciando um repositório local
Um repositório Git é apenas um
diretório com algumas metainformações sobre as alterações
dos arquivos do projeto que está no diretório.
A lista de comandos 1
mostra como criar um repositório Git do zero.
Note que foi criado um diretório oculto, por que começa com
um ponto (.), e por isso só é listado (ls) quando
se usa o parâmetro -a.
~$ mkdir greetings // (1)
~$ cd greetings // (2)
~/greetings$ ls -a // (3)
. ..
~/greetings$ git init // (4)
Initialized empty Git repository in home/fulano/greetings/.git/
~/greetings$ ls -a // (5)
. .. .git
-
Cria diretório greetings, onde colocaremos o código do nosso projeto.
-
Acessa diretório greetings.
-
Lista os arquivos do diretório, incluindo arquivos ocultos.
-
Cria um repositório a partir do diretório atual.
-
Lista arquivos do diretório, incluindo o diretório
.gitque é um diretório oculto.
A lista com todos os arquivos
e subdiretórios criado pelo comando git init pode ser
vista na lista de comandos 2.
O comando ls .git foi usado para exibir essas informações.
O diretório .git contém metadados.
Ou seja, é um diretório com dados para o Git
controlar os dados do repositórios.
É a forma do Git "lembrar" da história do projeto.
Um repositório Git nada mais é do que um diretório com um
subdiretório .git adequadamente estruturado.
O subdiretório .git não deve ser alterado diretamente.
Suas alterações devem ser feitas através do comando git
acompanhado dos parâmetros correspondentes à ação desejada.
~/greetings$ ls .git/
HEAD branches config description hooks index info logs objects packed-refs refs
2.1. O comando git status
Um comando que é usado o tempo todo em um repositório Git é o
comando git status,
apresentado na lista de comandos 3.
Apesar desse comando estar em uma seção dedicada a ele,
devido a sua importância, ele não será abordado em profundidade,
uma vez que nosso objetivo aqui é mostrar uma utilização do Git
com poucos comandos, sem explorá-los por completo.
~/greetings$ git status
On branch master // (1)
No commits yet // (2)
nothing to commit (create/copy files and use "git add" to track) // (3)
-
A resposta desta linha é
On branch master. Banches são ramificações de um projeto Git, que podem tomar rumos diferentes durante seu desenvolvimento. Diferentes ramos podem ser mesclados ou se tornarem novos projetos. O nomemasteré o nome padrão para o ramo inicial do projeto Git. Não existe nenhuma exigência de que exista um ramo com esse nome no projeto. -
Esta linha mostra
No commits yet. Os commits são fotografias do sistema que o Git mantém em seus metadados no diretório.git. Como não fizemos nenhum commit ainda, não existe nenhuma "fotografia" no Git. -
Aqui aparece
nothing to commit (creat/copy files and use "git add" to track). Não há nada para "fotografar" (commit) por que o diretório do projeto está vazio. Nenhum arquivo está sendo monitorado. Para monitorar um arquivo temos que usar o comandogit add, que é apresentado na próxima seção.
2.2. Criando um arquivo novo
Como pode ser traduzido da terceira linha de resposta da lista de comandos
3, o Git monitora (track) arquivos criados
ou copiados para dentro do diretório do repositório.
A lista de comandos 4 mostra o conteúdo que queremos no arquivo
greet.py. Este arquivo em texto simples pode ser criado
dentro do diretório ou copiado para dentro dele.
É um arquivo escrito na linguagem de programação Python 3.
Porém, não é necessário saber Python para acompanhar este
tutorial. Basta notar que o arquivo será alterado e cada
alteração será monitorada pelo Git.
~/greetings$ cat greet.py / (1)
print("hello")
~/greetings$ python greet.py // (2)
hello
~/greetings$ ls -a // (3)
. .. .git greet.py
-
Mostra o conteúdo do arquivo
greet.py. -
Executa o arquivo criado com o comando
python greed.py. (Não é necessário executar essa linha para acompanhar este tutorial.) -
Só para mostrar que o arquivo
greed.pyfoi criado.
Depois de criado o arquivo greet.py, o comando
git status mostrará uma resposta um pouco diferente,
como mostra a lista de comandos 5.
Apenas as duas primeiras linhas cntinuam iguais.
~/greetings$ git status
On branch master
No commits yet
Untracked files: // (1)
(use "git add <file>..." to include in what will be committed)
greet.py
nothing added to commit but untracked files present (use "git add" to track) // (2)
-
Essa linha de resposta diz que o arquivo
greet.pynão está sendo monitorado (untracked). -
Veja que a resposta do comando já diz como adicionar a modificação no monitoramento (
git add <file>).
2.3. Adicionando um arquivo em stage
Aqui é um ponto que merece uma atenção especial quando se usa o Git. O Git só "fotografa" (commit) as alterações que estão em uma área abstrata de sua organização chamada stage. Isso por que, muitas vezes fazemos alterações que não queremos gravar. Testamos algo, não gostamos do resultado, e queremos descartar o que foi feito. Outras vezes, queremos gravar só algumas alterações, mas não todas. Esse processo também nos permite fazer alterações variadas e agrupá-las em fotografias separadas.
A lista de comandos 6 mostra como adicionar um arquivo na área de
stage do Git, com o comando git add greet.py.
Note que agora o arquivo está sendo monitorado, mas ainda não
foi "fotografado" (committed).
Se você colocar um arquivo na área de stage por engano,
pode removê-lo de lá, sem excluí-lo do diretório, com o
comando git rm --cached <file>, como mostra a resposta
do comando git status.
~/greetings$ git add greet.py
~/greetings$ git status
On branch master
No commits yet
Changes to be committed: // (1)
(use "git rm --cached <file>..." to unstage) // (2)
new file: greet.py // (3)
-
Mostra que existem alterações que podem ser fotografadas.
-
Mostra como retirar um arquivo da área de stage.
-
Indica que
greet.pyé um arquivo novo. Isto é, um arquivo que não estava sendo monitorado, mas poderá ser monitorado se fizer parte do próximo commit. É isso que faremos agora.
2.4. Monitorando o arquivo criado
É importante resaltar que até o momento, nenhum arquivo está
sendo monitorado pelo Git.
O arquivo greet.py está pronto para ser "fotografado" e,
a partir daí, ser monitorado.
Para fotografar as mudanças que estão na área de stage
deve-se executar o comando da lista de comandos 7.
O comando só será aceito se você estiver com
seu nome e email configurado.
Para não entrar em detalhes de configuração agora,
você pode digitar os comandos
git config user.name 'SEU_PRIMEIRO_NOME SEU_ULTIMO_NOME' e
git config user.email 'SEU_EMAIL@example.com'.
~/greetings$ git commit -m 'primeira fotografia do sistema'
[master (root-commit) 06cbe0b] primeira fotografia do sistema
1 file changed, 1 insertion(+)
create mode 100644 greet.py
Quando se executa o comando git commit sem o parâmetro
-m 'comentário' o Git abre um editor de texto para que
um comentário sobre a fotografia seja escrito.
O Git não permite commits sem comentários.
Então, foi usado aqui o parametro -m para ficar mais
resumido e visível através das listas de comandos.
Se você quiser ver a fotografia tirada do sistema
pode usar o comando git show e terá um resultado
parecido com o da lista de comandos 8.
Vamos entender essa fotografia.
~/greetings$ git show // (1)
commit 06cbe0b360ee871baf55d48aa1914d8b73708b4b (HEAD -> master) // (2)
Author: Francisco de Assis Boldt <fboldt@gmail.com> // (3)
Date: Tue Dec 22 08:21:39 2020 -0300 // (4)
primeira fotografia do sistema // (5)
diff --git a/greet.py b/greet.py
new file mode 100644
index 0000000..11b15b1
--- /dev/null // (6)
+++ b/greet.py // (7)
@@ -0,0 +1 @@
+print("hello") // (8)
-
O comando
git show. -
Logo depois da palavra commit está o hash da fotografia. O hash é a assinatura, o identificador, da fotografia. Podemos usar esse identificador para acessar a fotografia posteriormente. Na mesma linha temos a palavra master, indicando que o ramo do projeto chamado master está atualizado de acordo com esta fotografia. Ainda na mesma linha temos a palavra HEAD seguida uma seta (->). Esta seta indica que o estado do sistema que estamos vendo no momento está apontando para o ramo master. Isso ficará mais claro a seguir.
-
Quem fez a fotografia (dados inseridos pelos comandos
git config …). -
Quando a fotografia foi feita.
-
O comentário inserido pelo comando
git commit. No nosso caso, após o parâmetro-m. -
O arquivo
/dev/nullindica que o arquivo ainda não existia em uma fotografia anterior. Esta é primeira fotografia que registra sua criação. Os três sinais de menos (-) indicam que as linhas seguintes iniciadas por-foram removidas do arquivo. Como o arquivo ainda não existia, nada foi removido. -
O nome do arquivo que foi alterado. As linhas que começam com o sinal
+são as que foram inseridas no arquivo. -
Apenas uma linha foi inserida nesse arquivo recém criado.
2.5. Como desfazer alterações?
Com o que foi mostrado neste capítulo, já dá para usar o Git
para desenvolver seus programas.
Nossos programas e outros documentos raramente são criados
de uma vez. Começamos com uma versão simples e vamos
incrementando versão após versão até finalizarmos o que
precisamos fazer.
Então, ao invés de fazer cópias dos nossos arquivos,
podemos simplesmente alterar o arquivo sem medo.
Por exemplo, digamos que fizemos uma alteração no arquivo
greet.py e o programa parou de funcionar.
Suponhamos que a alteração foi tão complicada que seria melhor
descartar todas as alterações feitas e começar tudo de novo.
Se ainda não executamos o comando git add greet.py, podemos
descartar as alterações antes delas entrarem na área de
stage. Basta executar o comando git checkout -- greet.py.
Tudo voltará como estava no início.
Mas, se você tinha achado que a alteração seria uma boa idéia
ou simplesmente executou o comando git add . sem querer,
nenhum motivo para desespero.
Basta usar o comando git reset -- greet.py.
O Comando git add . adiciona na área de stage todas as alterações feitas no repositório.
Se você usar o comando git reset todas as adições para
a área de stage serão removidas para a lista de
não monitorados. Daí você pode adicionar em stage somente
os arquivos que você deseja na próxima fotografia.
Em resumo, você já pode usar o Git de maneira eficiente para implementar seus programas ou escrever seus documentos. Nos próximos capítulos você vai conhecer mais alguns comandos do Git que vão lhe ajudar a desenvolver seus trabalhos de forma mais eficiente e segura. Recomendo que você aprenda a usar um repositório remoto, de preferência na nuvem, em uma plataforma como o GitHub. Entretanto, se você já sabe como fazer isso, ou não tem interesse em usar um repositório remoto, você pode pular o capítulo seguinte e ir direto para o capítulo 4.
3. Repositório remoto no GitHub
Para criar uma conta no GitHub basta acessar o site
github.com e clicar em um botão escrito Sign up,
ou colocar o endereço github.com/join direto na
barra de endereços de um navegador web.
É necessário preencher os campos com
-
um nome de usuário (Username) que ainda não exista;
-
um endereço de email válido;
-
uma senha com pelo menos 15 caracteres alphanuméricos ou uma senha com pelo menos 8 caracteres que contenha pelo menos um (1) número e uma (1) letra minúscula.
Após ter o cadastro efetuado e confirmado pelo email cadastrado, é possível entrar no sistema pelo endereço github.com/login. Se o login e a senha estiverem corretos, a página aberta terá a divisão apresentada na figura 3. Ao clicar na sua foto ou símblo que o GitHub cria, é possível acessar seu perfil (Your profile), seus repositórios (Your repositories) etc.
Para criar um repositório novo (figura 4) é necessário inserir um nome de repositório que não exista na sua lista. A descrição do repositório é opcional, mas aqui nós colocaremos O "Hello World" do Git. Quando o repositório é público (public) qualquer pessoa pode visualizá-lo, mas quando é privado (private) só você pode visualizá-lo.
Para este tutorial, antes de criar o repositório, marque a opção "Add a README file" (adicionar arquivo README), como mostra a figura 5. Agora é só clicar no botão "Create a repository" (criar repositório).
3.1. Fazendo uma cópia local do repositório
Agora que o repositório está criado, é necessário fazer um cópia local dele para poder alterá-lo. O link para fazer essa cópia pode ser encontrado clicando-se no botão "Clone" do repositório.
Se você fez os passos do capítulo anterior, antes de continuar o tutorial deste capítulo você precisa excluir ou renomear o repositório anterior.
Depois de copiado o link, usasse o comando git clone <link>
para fazer o download do repositório no computador local,
como mostra a lista de comandos 9.
~$ git clone https://github.com/fboldt/greetings.git
Cloning into 'greetings'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 619 bytes | 619.00 KiB/s, done.
3.2. O comando git log
Agora, já é possível acessar o diretório criado e verificar que já existe fotografia (commit) do repositório. Esta foto foi "tirada" quando inserimos o arquivo "README.md", marcando a opção "Add a README file" ao criar o repositório no GitHub.
~$ cd greetings/ //(1)
~/greetings$ git log //(2)
commit 58da81bbc897dcdf877530ae972fd2d4b3cc9c8d (HEAD -> main) //(3)
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Tue Dec 22 08:29:25 2020 -0300
Initial commit
-
Acessa repositório clonado.
-
Lista fotografias do repositório.
-
Note que o ramo (branch) criado pelo GitHub se chama
maine nãomastercomo mostrado no capítulo anterior. É apenas uma preferência do GitHub. Mas esse nome pode ser alterado se você quiser.
3.3. Alterando a cópia local
Para continuar, crie (ou copie) o arquivo greet.py
de forma que ele tenha o conteúdo mostrado na listagem
11.
~/greetings$ cat greet.py
print("Hello!")
O comando git status agora traz uma informação a mais,
como mostra a listagem 12.
Agora aparece a linha Your branch is up to date with 'origin/main'. informando que a cópia local do repositório está
atualizada com o repositório remoto hospedado no GitHub.
~/greetings$ git status
On branch main
Your branch is up to date with 'origin/main'.
Untracked files:
(use "git add <file>..." to include in what will be committed)
greet.py
nothing added to commit but untracked files present (use "git add" to track)
Vamos adicionar o arquivo greet.py na área de stage,
como na listagem 13.
~/greetings$ git add greet.py
~/greetings$ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: greet.py
O próximo passo é fotografar as alteração da área de stage, como na listagem 14.
~/greetings$ git commit -m 'cria arquivo greet.py'
[main 6c8951a] cria arquivo greet.py
1 file changed, 1 insertion(+)
create mode 100644 greet.py
Note que os comandos e suas respectivas respostas neste capítulo estão muito parecidos com os do capítulo anterior. Por isso, algumas informações contidas lá não estão sendo repetidas aqui.
3.4. Atualizando a cópia remota
Para atualizar o repositório remoto usa-se o comando
git push, como mostra a listagem 15.
~/greetings$ git push
Username for 'https://github.com': fboldt //(1)
Password for 'https://fboldt@github.com': //(2)
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 311 bytes | 311.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/fboldt/greetings.git
58da81b..6c8951a main -> main
-
Insere nome de usuário com autorização para alterar o repositório.
-
Insere a senha do usuário.
Ao acessar o repositório no GitHub, pode-se ver as alterações atualizadas, como mostra a figura 7.
Alterações também podem ser feitas diretamente no site do
GitHub.
Por exemplo, para alterar o arquivo README.md, basta clicar no
lápis da figura 7.
Vamos mudar o título de # greetings para # Hello Git,
como na figure 8, e depois clicar em Commit changes
para fotografar esta alteração.
3.5. Atualizando o repositório local
Para verificar se o repositório remoto foi alterado,
usa-se o comando git fetch, como na listagem 16.
~/greetings$ git fetch
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 683 bytes | 683.00 KiB/s, done.
From https://github.com/fboldt/greetings
6c8951a..933fc74 main -> origin/main
O comando git status da listagem 17
mostra que nossa cópia local está desatualizada por
1 fotografia (1 commit), e pode ser atualizada pelo
comando git pull.
~/greetings$ git status
On branch main
Your branch is behind 'origin/main' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
nothing to commit, working tree clean
Então, podemos executar o comando git pull, como na listagem
18.
~/greetings$ git pull
Updating 6c8951a..933fc74
Fast-forward
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Agora o arquivo local está igual ao arquivo remoto, como pode ser visto na listagem 19.
git pull.~/greetings$ cat README.md
# Hello Git
O "Hello World" do Git.
3.6. Vantagens de ter um repositório remoto
Dentre algumas vantagens de se ter um repositório na nuvem, podemos citar algumas.
-
Pode ser usado como backup.
-
Pode ser usado como repositório central para sincronizar vários computadores.
-
Disponibilizar o código para outras pessoas.
-
Trabalhar em equipe.
Você não precisa necessariamente usar a plataforma GitHub. Existem outras plataformas que também possuem tipos de contas sem custo para o usuário, como por exemplo, Bitbucket e GitLab, para citar algumas.
4. Criando fotografias novas e acessando fotografias antigas
O Git só vai tirar uma nova fotografia do sistema se algo for alterado e colocado na área de stage. A lista de comandos 20 mostra a alteração sugerida para esta parte do tutorial. O código foi alterado mas seu resultado do programa continuou igual. É uma boa prática de programação refatorarmos os nossos códigos para prepará-los para alterações de comportamento e adição de funcionalidades. Nesse caso, o programa é extremamente simples. Tal alteração seria desnecessária, mas é uma boa forma de mostrar como utilizar o Git em um processo de refatoração.
~/greetings$ cat greet.py
def main():
print("Hello!")
main()
Depois da alteração do arquivo, o comando git status
apresenta um retorno diferente, como mostra a listagem
21.
Novamente o arquivo greet.py não esta na área de stage,
mas agora esse arquivo está sendo monitorado.
Então, temos duas opções:
descartar as alterações com o comando
git restore greet.py ou adicionar
as alterações na área de stage com o comando
git add greet.py.
~/greetings$ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed) // (1)
(use "git restore <file>..." to discard changes in working directory) // (2)
modified: greet.py
no changes added to commit (use "git add" and/or "git commit -a")
-
Mostra como adicionar um arquivo na área de stage.
-
Mostra como descartar as alterações feitas no arquivo.
Adicionaremos as alterações na área de stage, como mostra a listagem 22.
~/greetings$ git add greet.py // (1)
~/greetings$ git status // (2)
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: greet.py
-
Adiciona o arquivo alterado na área de stage.
-
O resultado do comando status mudou novamente.
O resultado do comando git status está muito parecido
com o da listagem 6. Agora, não aparece
mais "arquivo novo" (new file), mas "modificado" (modified).
A listagem 23 mostra o comando git commit com o
parâmetro -m e um comentário relacionado à alteração feita.
~/greetings$ git commit -m 'cria função main' // (1)
[main e0fe2b3] cria função main
1 file changed, 4 insertions(+), 1 deletion(-) // (2)
-
Registro da fotografia com um comentário que resume as alterações fotografadas.
-
Mostra que apenas 1 arquivo foi alterado (1 file changed), 4 linhas foram inseridas (4 insertions(+)) e 1 linha foi removida (1 deletion(-)).
O comando git show, na listagem 24,
mostra como ficou a fotografia.
~/greetings$ git show
commit e0fe2b32abaa5b4bcb7a1889a820f155e9ec635e (HEAD -> main)
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Wed Dec 23 08:24:50 2020 -0300
cria função main
diff --git a/greet.py b/greet.py
index 693eaec..55bb9ae 100644
--- a/greet.py // (1)
+++ b/greet.py // (2)
@@ -1 +1,4 @@
-print("Hello!") // (3)
+def main(): // (4)
+ print("Hello!") // (4)
+ // (4)
+main() // (4)
-
Versão anterior do arquivo
-
Versão atual do arquivo
-
Linha removida.
-
Linhas inseridas.
Note que qualquer alteração em uma linha considera aquela linha como removida e outra linha com a alteração como inserida. Vamos fazer mais uma alteração no sistema, que pode ser vista na listagem 25. Novamente, o código foi alterado sem alterar o comportamento do programa.
~/greetings$ cat greet.py
def main():
print("Hello!")
if __name__ == "__main__":
main()
Depois dessa alteração, o comando git status
apresentará o mesmo retorno visto na listagem 21.
Vamos adicionar à área de stage a nova alteração com
o comando git add greet.py.
Após executado esse comando, o status do repositório
será igual ao apresentado na listagem 22.
Agora estamos prontos para executar o comando commit
como mostra a lista de comandos 26.
~/greetings$ git commit -m 'verifica se é o programa principal'
[main bd61894] verifica se é o programa principal
1 file changed, 2 insertions(+), 1 deletion(-)
Novamente, podem ser vistas as alterações feitas, como mostrado na listagem 27.
~/greetings$ git show
commit bd618942ddf84ad2ceb062b7ef53c22b12a94dae (HEAD -> main)
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Wed Dec 23 08:55:49 2020 -0300
verifica se é o programa principal
diff --git a/greet.py b/greet.py
index 55bb9ae..3062fd5 100644
--- a/greet.py
+++ b/greet.py
@@ -1,4 +1,5 @@
def main():
print("Hello!")
-main() // (1)
+if __name__ == "__main__": // (2)
+ main() // (2)
-
Linha removida.
-
Linhas inseridas.
Agora temos cópias seguras das versões anteriores do nosso projeto.
4.1. Listando as fotografias do repositório
A listagem 28 mostra como listar as fotografias do
sistema com o comando git log.
A opção --oneline foi usada aqui para que
as fotografias sejam vistas de um forma mais compacta.
Mas você deve testar sem essa opção também.
~/greetings$ git log --oneline
bd61894 (HEAD -> main) verifica se é o programa principal // (1)
e0fe2b3 cria função main
933fc74 (origin/main, origin/HEAD) Update README.md // (2)
6c8951a cria arquivo greet.py
58da81b Initial commit
-
Fotografia com o estado atual do repositório local. A palavra HEAD está nesta linha.
-
Fotografia com o estado atual do repositório remoto. As palavras origin/HEAD estão nesta linha. Neste caso, origin indica o repositório remoto.
A palavra HEAD indica o estado atual do repositório,
seja ele local ou remoto.
As fotografias do repositório são apresentadas em ordem
cronológica reversa. Ou seja, a última fotografia registrada
é a primeira a ser apresentada pelo comando git log.
No início de cada linha vemos uma parte do hash de cada
fotografia. Em geral, essa parte do hash é suficiente para
visualizar ou acessar uma fotografia.
Por exemplo, é possível ver uma fotografia mais antiga
(ou mais recente) com o comando git show <hash>,
onde normalmente, os quatro primeiros caracteres
da parte do hash que aparece na listagem
28 é suficiente para identificá-la.
4.2. Mostrando o conteúdo de fotografias
Na listagem 29 o comando git show
mostra a fotografia anterior usando apenas a parte de seu hash
listada na listagem 28.
Note que o resultado da listagem 29 é identico
ao da listagem 24.
Ao seguir esses passos, lembre-se de substituir
o hash 'e0fe2b3' pelo hash que aparece na sua
lista de logs. Certamente terá um valor diferente.
~/greetings$ git show e0fe2b3
commit e0fe2b32abaa5b4bcb7a1889a820f155e9ec635e
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Wed Dec 23 08:24:50 2020 -0300
cria função main
diff --git a/greet.py b/greet.py
index 693eaec..55bb9ae 100644
--- a/greet.py
+++ b/greet.py
@@ -1 +1,4 @@
-print("Hello!")
+def main():
+ print("Hello!")
+
+main()
A listagem 30 mostra a primeira fotografia do
arquivo greet.py no repositório.
~/greetings$ git show 6c8951a
commit 6c8951a5c2979932ffaed078139616584afd8543
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Tue Dec 22 08:41:06 2020 -0300
cria arquivo greet.py
diff --git a/greet.py b/greet.py
new file mode 100644
index 0000000..693eaec
--- /dev/null
+++ b/greet.py
@@ -0,0 +1 @@
+print("Hello!")
O comando git show <hash> é muito útil para
verificarmos se uma determinada fotografia contém
as alteração que precisamos.
Despois de confirmarmos nossas suspeitas, podemos
voltar o repositório para o estado que desejarmos.
4.3. Alterando o estado do sistema
O comando git checkout permite colocar o repositório
em um estado gravado em alguma fotografia.
A listagem 31 mostra como fazer o repositório
voltar para o estado em que a função main do programa
greet foi criada. Algumas linhas do resultado foram
substituídas por "…". Então, mais informações
aparecerão quando você digitar esse comando.
Ao seguir esses passos, lembre-se de substituir
o hash 'e0fe2b3' pelo hash que aparece na sua
lista de logs. Certamente terá um valor diferente.
~/greetings$ git checkout e0fe2b3
Note: switching to 'e0fe2b3'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
...
HEAD is now at e0fe2b3 cria função main
Veja na listagem 32 que o programa greet.py
voltou ao seu estado anterior.
~/greetings$ cat greet.py
def main():
print("Hello!")
main()
Ao listar as fotografias do repositório, como mostra a figura
33, o comando git log não mostra mais o brach main, nem a fotografia da última alteração feita.
Além disso, HEAD agora está na fotografia e0fe2b3.
~/greetings$ git log --oneline
e0fe2b3 (HEAD) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
Você pode estar se perguntando "Git é então um complexo ctrl+z?".
Claro que não!
A fotografia mais recente continua sendo monitorada e
pode ser visualizada com a opção --all
no comando git log, como mostra a
figura 34.
~/greetings$ git log --oneline --all
bd61894 (main) verifica se é o programa principal
e0fe2b3 (HEAD) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
Na verdade, o Git quase sempre adiciona informação ao repositório. Mesmo sendo possível remover informações de um repositório, isso é raramente recomendado. A figura 35 mostra como colocar o sistema no estado da fotografia mais recente.
~/greetings$ git checkout main
Previous HEAD position was e0fe2b3 cria função main
Switched to branch 'main'
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
Qualquer alteração nos arquivos monitorados pelo repositório
deve ser feita enquanto o estado do repositório (HEAD)
está apontando para um ramo (branch).
Fotografias de alterações feitas fora de ramos não
aparecem na resposta do comando git log, nem com a opção
--all`.`
4.4. Criando etiquetas para fotografias
Para facilitar o acesso das fotografias pode-se etiquetá-las.
O tipo de etiqueta mais comum é mostrado na figura
36, que usa o comando git tag com a
opção -a. Esta opção permite usar a opção
-m para inserir um comentário na etiqueta.
~/greetings$ git tag -a v0.3 -m 'Versão bem complexa para um programa Hello World'
~/greetings$ git log --oneline --all // (1)
bd61894 (HEAD -> main, tag: v0.3) verifica se é o programa principal // (2)
e0fe2b3 cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
-
Lista fotografias do repositório.
-
Mostra a tag "v0.3" na linha correspondente à fotografia.
O comando git tag coloca a etiqueta na fotografia atual
do sistema, mas é possível etiquetar outras fotografias
através de seu hash, como mostra a figura 37.
~/greetings$ git tag -a v0.1 -m 'Versão clássica' 6c8951a
~/greetings$ git log --oneline --all
bd61894 (HEAD -> main, tag: v0.3) verifica se é o programa principal
e0fe2b3 cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a (tag: v0.1) cria arquivo greet.py
58da81b Initial commit
~/greetings$ git tag v0.2 e0fe2b3
~/greetings$ git log --oneline --all
bd61894 (HEAD -> main, tag: v0.3) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a (tag: v0.1) cria arquivo greet.py
58da81b Initial commit
A figura 9 mostra coma acessar uma fotografia antiga através de sua etiqueta
~/greetings$ git checkout v0.2
Note: switching to 'v0.2'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.
...
HEAD is now at e0fe2b3 cria função main
~/greetings$ git log --oneline --all
bd61894 (tag: v0.3, main) verifica se é o programa principal
e0fe2b3 (HEAD, tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a (tag: v0.1) cria arquivo greet.py
58da81b Initial commit
O comando git tag pode ser usado para listar as
etiqueta, como mostra a figura 40.
~/greetings$ git tag
v0.1
v0.2
v0.3
Listagens mais complexas, com caracteres coringa por exemplo, podem ser feitas com esse comando, mas não serão exploradas aqui.
Quando se executa o comando git show com uma etiqueta,
ele mostra também os dados da etiqueta, como pode ser visto na
figura 41.
A informação de quem fez a etiqueta (tagger) e de quando
a etiqueta foi criada só é gravada se a opção `-a
for usada na criação dela.
~/greetings$ git show v0.2
commit e0fe2b32abaa5b4bcb7a1889a820f155e9ec635e (tag: v0.2)
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Wed Dec 23 08:24:50 2020 -0300
cria função main
diff --git a/greet.py b/greet.py
index 693eaec..55bb9ae 100644
--- a/greet.py
+++ b/greet.py
@@ -1 +1,4 @@
-print("Hello!")
+def main():
+ print("Hello!")
+
+main()
~/greetings$ git show v0.3
tag v0.3
Tagger: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Wed Dec 23 09:11:24 2020 -0300
Versão bem complexa para um programa Hello World
commit bd618942ddf84ad2ceb062b7ef53c22b12a94dae (HEAD -> main, tag: v0.3)
...
É importante notar que HEAD não aponta para nenhum branch. No caso, não aponta para main, que é o único branch do repositório. Para continuar o tutorial execute o comando da figura [fig:29], para que HEAD aponte para main.
~/greetings$ git checkout main
Switched to branch 'main'
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
5. Ramos no projeto
As etiquetas são fixadas em uma fotografia, mas ramos (braches) são vivos e acompanham novas fotografias que são criadas. Há muitas formas de se usar os braches. Neste capítulo mostraremos uma delas. Também há vários motivos para se usar os branches. Um deles é que você pode inserir uma alteração instável no sistema e querer que essa alteração fique gravada. Ou seja, você fez uma alteração que não está pronta, mas quer que essa alteração seja monitorada pelo Git por algum motivo. Talvez você não tenha certeza que o próximo passo vai funcionar, ou talvez você queira testar o próximo passo de mais do que uma forma. Ou ainda, pode ser que outra pessoa termine essa atualização parcial que você fez. O fato é que você não quer que esta seja a versão usada até que ela esteja terminada.
5.1. Criando ramos
Como ilustração, faremos uma versão brasileira para o nosso programa. Como eu supostamente ainda não sei se isso será fácil ou difícil de terminar, farei um branch como mostra a figura 44. Agora a fotografia mais recente tem dois ramos (na cor verde), main e pt-br.
~/greetings$ git branch pt-br
~/greetings$ git log --oneline --all
bd61894 (HEAD -> main, tag: v0.3, pt-br) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
Para fazer um alteração no ramo pt-br, deve-se mudar HEAD para esse ramo, como apresentado na figura 1. Agora HEAD aponta para pt-br.
~/greetings$ git checkout pt-br
Switched to branch 'pt-br'
~/greetings$ git log --oneline --all
bd61894 (HEAD -> pt-br, tag: v0.3, main) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
~/greet
Quando só existia o ramo main, cada comando
commit movia o ramo main para a
fotografia mais recente.
Agora que HEAD aponta para pt-br,
o comando commit vai mover o ramo pt-br
para as novas fotografias, deixando o ramo
main na fotografia atual.
Assim, fica claro para todos os envolvidos no projeto
que o ramo main contém uma versão estável
do sistema.
5.2. Uma alteração incompleta para o ramos atual
Como ilustração será feita a alteração proposta na figura 45.
~/greetings$ cat greet.py
def main():
print("Olá!")
if __name__ == "__main__":
main()
A resposta do comando git status da figura
46 já é conhecida.
A única diferença do que já foi visto é a primeira linha
que mostra que ramo atual é o pt-br
(On branch pt-br).
~/greetings$ git status
On branch pt-br
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: greet.py
no changes added to commit (use "git add" and/or "git commit -a")
O status após adicionar a alteração na área de stage mostrado na figura 47 também não é muito diferente do que já foi visto.
~/greetings$ git add greet.py
~/greetings$ git status
On branch pt-br
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: greet.py
O resultado dos comandos git commit
e git show apresentados na
figura 49 também não apresentam muita novidade.
~/greetings$ git commit -m 'versão brasileira'
[pt-br 8828ea9] versão brasileira
1 file changed, 1 insertion(+), 1 deletion(-)
~/greetings$ git show
commit 8828ea9256bc157d561bab306c01f304b3a54821 (HEAD -> pt-br)
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Wed Dec 23 11:34:03 2020 -0300
versão brasileira
diff --git a/greet.py b/greet.py
index 3062fd5..66da5e9 100644
--- a/greet.py
+++ b/greet.py
@@ -1,5 +1,5 @@
def main():
- print("Hello!")
+ print("Olá!")
if __name__ == "__main__":
main()
Note que o ramo main não tem nada de especial. Usar outro nome para um ramo não muda nada no processo de fotografar as versões do sistema.
~/greetings$ git log --oneline --all
8828ea9 (HEAD -> pt-br) versão brasileira
bd61894 (tag: v0.3, main) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
5.3. Terminado a alteração desejada
Para mostrar como colocar uma alteração no ramo estável do sistema, vamos fazer a alteração proposta na figura 51. Estamos considerando o ramo estável deste repositório o ramo main, mas poderia ser qualquer outro nome.
~/greetings$ cat greet.py
import sys
def main():
if len(sys.argv)>1 and sys.argv[1]=='pt-br':
print("Olá!")
else:
print("Hello!")
if __name__ == "__main__":
main()
~/greetings$ python greet.py
Hello!
~/greetings$ python greet.py pt-br
Olá!
Depois de colocar a nova alteração na área de stage
(git add greet.py)
e executar o comando git commit podemos ver a nova
fotografia listada na figura 53.
~/greetings$ git add greet.py
~/greetings$ git commit -m 'versão brasileira parametrizada'
[pt-br 2aa634b] versão brasileira parametrizada
1 file changed, 5 insertions(+), 1 deletion(-)
~/greetings$ git log --oneline --all
2aa634b (HEAD -> pt-br) versão brasileira parametrizada
8828ea9 versão brasileira
bd61894 (tag: v0.3, main) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
A figura 54 mostra como ficou a fotografia mais recente do repositório. Também mostra como executar o programa na versão mais recente, caso ache interessante.
~/greetings$ git show
commit 2aa634b3fe78d227bd07482dfb080154e02cc93f (HEAD -> pt-br)
Author: Francisco de Assis Boldt <fboldt@gmail.com>
Date: Wed Dec 23 11:49:08 2020 -0300
versão brasileira parametrizada
diff --git a/greet.py b/greet.py
index 66da5e9..3e2fb6e 100644
--- a/greet.py
+++ b/greet.py
@@ -1,5 +1,9 @@
+import sys
def main():
- print("Olá!")
+ if len(sys.argv)>1 and sys.argv[1]=='pt-br':
+ print("Olá!")
+ else:
+ print("Hello!")
if __name__ == "__main__":
main()
5.4. Mesclando o ramo atual com o ramo principal
Agora que a alteração já foi finalizada, é hora de
mesclar a atualização no ramo principal.
A figura 55 apresenta um procedimento que pode
ser executado com essa finalidade.
Primeiro, temos que fazer HEAD apontar
para o ramo principal com o comando
git checkout main.
Depois, usamos o comando git merge pt-br
para mesclar o ramo pt-br com o ramo atual.
~/greetings$ git checkout main
Switched to branch 'main'
Your branch is ahead of 'origin/main' by 2 commits.
(use "git push" to publish your local commits)
~/greetings$ git merge pt-br
Updating bd61894..2aa634b
Fast-forward
greet.py | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
A figura 56 mostra a lista de fotografias depois da mesclagem de ramos.
~/greetings$ git log --oneline --all
2aa634b (HEAD -> main, pt-br) versão brasileira parametrizada
8828ea9 versão brasileira
bd61894 (tag: v0.3) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
Na segunda linha da reposta do comando
git merge pt-br na figura 55
está escrito Fast-forward.
Isso significa que nenhuma alteração foi feita no
ramo main enquanto o ramo pt-br
estava sendo alterado.
Assim, não houve nenhum conflito para juntar as versões
porque a versão mais recente de pt-br
era como uma versão futura de main.
A seguir, veremos um situação que isso não é resolvido tão
facilmente.
6. Criando bifurcações no projeto
O capítulo anterior mostrou uma mesclagem do tipo fast-forward, que é um tipo sem conflito. Aqui, veremos como resolver conflitos quando ele acontecem.
6.1. Criando um ramo comum
Agora faremos uma versão do sistema em alemão. Para manter uma boa prática de Git vamos criar um novo ramo, como mostra a figura 57.
~/greetings$ git branch de
~/greetings$ git log --oneline --all
2aa634b (HEAD -> main, pt-br, de) versão brasileira parametrizada
8828ea9 versão brasileira
bd61894 (tag: v0.3) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
~/greetings$ git checkout de
Switched to branch 'de'
Para trabalhar no novo ramo, deve-se usar o comando
git checkout. O comando git log
mostra o ramo para o qual HEAD aponta.
Depois de fazer a alteração sugerida na figura 58,
execute o comando git commit para deixar
gravada as alterações no repositório.
~/greetings$ cat greet.py
import sys
def main():
if len(sys.argv)>1 and sys.argv[1]=='pt-br':
print("Olá!")
elif len(sys.argv)>1 and sys.argv[1]=='de':
print("Hallo!")
else:
print("Hello!")
if __name__ == "__main__":
main()
~/greetings$ python greet.py
Hello!
~/greetings$ python greet.py pt-br
Olá!
~/greetings$ python greet.py de
Hallo!
A fotografia do último commit está na figura 60.
~/greetings$ git add greet.py
~/greetings$ git commit -m 'versão alemã parametrizada'
[de 54a47d0] versão alemã parametrizada
1 file changed, 2 insertions(+)
A figura 61 mostra que o sistema possui seis fotografias até o momento.
~/greetings$ git log --oneline --all
54a47d0 (HEAD -> de) versão alemã parametrizada
2aa634b (pt-br, main) versão brasileira parametrizada
8828ea9 versão brasileira
bd61894 (tag: v0.3) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
Na condição atual, no exemplo co capítulo anterior, o ramo foi mesclado com o ramo estável. Mas para exemplificar um conflito, não vamos mesclá-lo agora. Um motivo para não mesclar é não ter feito todos os testes no seu ramo. Ou o ramo ainda não está terminado. Vamos supor me nossa situações hipotética que não temos certeza que a resposta correta em alemão é hallo. Por isso, vamos adiar a mesclagem com o ramo principal.
6.2. Criando mais um ramo comum
Normalmente, conflitos de mesclagem não são criados intencionalemente. Mas para ilustrar a resolução de conflitos que inevitavelmente acontecerão, vamos fazer uma versão em italiano do nosso sistema para forçar um conflito. Para isso, vamos começar criando um novo ramo a partir de main. Após fotografarmos a alteração do sistema com a versão italiana, teremos dois ramos que nasceram a partir de main. Um deles é facilmente mesclável. O outro, nem tanto.
Uma forma de se criar um ramo a partir de main
é estando com HEAD apontando para main.
Em seguida, usa-se o comando git branch para
criar um novo branch, como na figura 62.
~/greetings$ git checkout main
Switched to branch 'main'
Your branch is ahead of 'origin/main' by 4 commits.
(use "git push" to publish your local commits)
~/greetings$ git branch it
~/greetings$ git checkout it
Switched to branch 'it'
Implemente a alteração sugerida na figura 63.
~/greetings$ cat greet.py
import sys
def main():
if len(sys.argv)>1 and sys.argv[1]=='pt-br':
print("Olá!")
elif len(sys.argv)>1 and sys.argv[1]=='it':
print("Ciao!")
else:
print("Hello!")
if __name__ == "__main__":
main()
Adicione as alterações na área de stage e execute
o comando git commit para fazer a nova fotografia.
Após adicionar as alterações na área de stage e executar
o comando git commit a fotografia mais atual
deverá estar parecida com a da figura 64.
~/greetings$ git add greet.py
~/greetings$ git commit -m 'versão italiana parametrizada'
[it 46244be] versão italiana parametrizada
1 file changed, 2 insertions(+)
~/greetings$ git log --oneline --all
46244be (HEAD -> it) versão italiana parametrizada
54a47d0 (de) versão alemã parametrizada
2aa634b (pt-br, main) versão brasileira parametrizada
8828ea9 versão brasileira
bd61894 (tag: v0.3) verifica se é o programa principal
e0fe2b3 (tag: v0.2) cria função main
933fc74 (origin/main, origin/HEAD) Update README.md
6c8951a cria arquivo greet.py
58da81b Initial commit
6.3. Listando as fotografias em forma de grafo
A opção --graph do comando git log
lista as fotografias do repositório em forma de grafo,
como na figura 65.
~/greetings$ git log --oneline --all --graph
* 46244be (HEAD -> it) versão italiana parametrizada
| * 54a47d0 (de) versão alemã parametrizada
|/
* 2aa634b (pt-br, main) versão brasileira parametrizada
* 8828ea9 versão brasileira
* bd61894 (tag: v0.3) verifica se é o programa principal
* e0fe2b3 (tag: v0.2) cria função main
* 933fc74 (origin/main, origin/HEAD) Update README.md
* 6c8951a cria arquivo greet.py
* 58da81b Initial commit
Note que acima do ramo main as linhas estão vermelhas, indicando um possível conflito. Observe que o ramo de (alemão), que é mais antigo que o ramo it (italiano), se mostra como um ramo que está saindo de um galho.
6.4. Mesclando o último ramo antes do primeiro
O último ramo criado foi o ramo it, mas aqui vasmos mesclá-lo ao ramo principal antes do ramo mais antigo, que é o ramo de. A figura 66 mostra uma forma de como isso pode ser feito. Ocorreu uma mesclagem do tipo fast-forward sem nenhum problema.
~/greetings$ git checkout main
Switched to branch 'main'
Your branch is ahead of 'origin/main' by 4 commits.
(use "git push" to publish your local commits)
~/greetings$ git merge it
Updating 2aa634b..46244be
Fast-forward
greet.py | 2 ++
1 file changed, 2 insertions(+)
Na figura 67 podemos ver que o grafo não foi alterado, mas agora HEAD e main estão na fotografia mais recente.
~/greetings$ git log --oneline --all --graph
* 46244be (HEAD -> main, it) versão italiana parametrizada
| * 54a47d0 (de) versão alemã parametrizada
|/
* 2aa634b (pt-br) versão brasileira parametrizada
* 8828ea9 versão brasileira
* bd61894 (tag: v0.3) verifica se é o programa principal
* e0fe2b3 (tag: v0.2) cria função main
* 933fc74 (origin/main, origin/HEAD) Update README.md
* 6c8951a cria arquivo greet.py
* 58da81b Initial commit
6.5. Quando não corre tudo bem na mesclagem
Agora, veja figura 68 o que ocorre quando tentamos mesclar o ramo alemão com o ramo princial.
~/greetings$ git merge de
Auto-merging greet.py
CONFLICT (content): Merge conflict in greet.py
Automatic merge failed; fix conflicts and then commit the result.
~/greetings$ cat greet.py
import sys
def main():
if len(sys.argv)>1 and sys.argv[1]=='pt-br':
print("Olá!")
<<<<<<< HEAD
elif len(sys.argv)>1 and sys.argv[1]=='it':
print("Ciao!")
=======
elif len(sys.argv)>1 and sys.argv[1]=='de':
print("Hallo!")
>>>>>>> de
else:
print("Hello!")
if __name__ == "__main__":
main()
~/greetings$ git status
On branch main
Your branch is ahead of 'origin/main' by 5 commits.
(use "git push" to publish your local commits)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: greet.py
no changes added to commit (use "git add" and/or "git commit -a")
~/greetings$ cat greet.py
import sys
def main():
if len(sys.argv)>1 and sys.argv[1]=='pt-br':
print("Olá!")
elif len(sys.argv)>1 and sys.argv[1]=='it':
print("Ciao!")
elif len(sys.argv)>1 and sys.argv[1]=='de':
print("Hallo!")
else:
print("Hello!")
if __name__ == "__main__":
main()
~/greetings$ git add greet.py
~/greetings$ git commit -m 'merge com versão alemã'
[main 4377f73] merge com versão alemã
~/greetings$ git log --oneline --all --graph
* 4377f73 (HEAD -> main) merge com versão alemã
|\
| * 54a47d0 (de) versão alemã parametrizada
* | 46244be (it) versão italiana parametrizada
|/
* 2aa634b (pt-br) versão brasileira parametrizada
* 8828ea9 versão brasileira
* bd61894 (tag: v0.3) verifica se é o programa principal
* e0fe2b3 (tag: v0.2) cria função main
* 933fc74 (origin/main, origin/HEAD) Update README.md
* 6c8951a cria arquivo greet.py
* 58da81b Initial commit
~/greetings$ python greet.py
Hello!
~/greetings$ python greet.py pt-br
Olá!
~/greetings$ python greet.py it
Ciao!
~/greetings$ python greet.py de
Hallo!
~/greetings$ git push
Username for 'https://github.com': fboldt
Password for 'https://fboldt@github.com':
Enumerating objects: 23, done.
Counting objects: 100% (23/23), done.
Delta compression using up to 8 threads
Compressing objects: 100% (20/20), done.
Writing objects: 100% (21/21), 2.14 KiB | 2.14 MiB/s, done.
Total 21 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4), done.
To https://github.com/fboldt/greetings.git
933fc74..4377f73 main -> main
~/greetings$ git log --oneline --all --graph
* 4377f73 (HEAD -> main, origin/main, origin/HEAD) merge com versão alemã
|\
| * 54a47d0 (de) versão alemã parametrizada
* | 46244be (it) versão italiana parametrizada
|/
* 2aa634b (pt-br) versão brasileira parametrizada
* 8828ea9 versão brasileira
* bd61894 (tag: v0.3) verifica se é o programa principal
* e0fe2b3 (tag: v0.2) cria função main
* 933fc74 Update README.md
* 6c8951a cria arquivo greet.py
* 58da81b Initial commit
7. Conclusão
Agora, você já sabe uma forma de se usar o Git.
A forma apresentada aqui não é a única, nem a melhor.
É um exemplo para ser aplicado imediatamente.
É claro que um projeto real, que necessite de um
gerenciador de versões, possívelmente terá mais arquivos
no que o exemplo hello world apresentado aqui.
Porém, trabalhar com mais arquivos pode facilitar o
gerenciamento das versões.
Conflitos geralmente ocorrem quando o mesmo arquivo
sofre alterações em ramos diferentes.