Git

A ferramenta indispensável

O que é Git?

O Git é uma um sistema open-source de controle de versão distribuído mais popular.

O Git é usado principalmente para o desenvolvimento de software, porém pode ser usado para registrar o histórico de edições de qualquer tipo de arquivo.

Ser open-source significa que qualquer pessoa utilizá-lo e contribuir com o projeto.

Ser um controle de versão significa que você pode controlar e ver o histórico de edições de um arquivo.

Ser um sistema distribuído neste caso, significa que todos os que utilizarem em um projeto terão seu próprio repositório local com todo o histórico de versões.

História do Git

Em 2002 a comunidade do desenvolvimento do kernel Linux começou a utilizar a ferramenta BitKeeper para o controle de versão.

Em 2005 a ferramenta BitKeeper começou a ser paga. Então Linux Torvalds (o criador do Linux), criou o Git baseado em lições aprendidas ao usar o BitKeeper.

Git é apenas para desenvolvedores?

Na verdade não, o Git é uma ferramenta comum para qualquer pessoa que deseja trabalhar com versões de documentos e em equipe.

O Git permite que grupos de pessoas trabalhem nos mesmos documentos (geralmente em código) ao mesmo tempo sem que um atrapalhe o outro.

Git não é um editor de documento colaborativo

Devido as descrições anteriores, sobre o Git permitir que pessoas trabalhem nos mesmos documentos ao mesmo tempo, pode ter ocasionado um mal entendido.

Se você imaginou o Git sendo um software como com Google Docs…

Houve um equívoco, a aparência do Git é algo neste estilo, um terminal.

bash
$ # Aqui iremos usar o Git a partir do terminal $

A título de curiosidade, também existe ferramentas externas com interface gráfica, como o GitKraken.

Git no mercado de trabalho

Conhecimento de Git muitas vezes acaba sendo implícito nos requisitos das vagas de emprego.

Como funciona o trabalho sem o Git?

Para ilustrar este cenário será utilizado um exemplo, que talvez tenha passado alguma vez na vida.

O Git será útil para diversos setores, no caso anterior foi demonstrado o problema que a falta de uma ferramenta de controle de versão pode causar.

Foi mostrado um caso de um aluno que estava enviando seu trabalho para um professor, e para cada revisão realizada, ele gerava uma versão nova do documento, porém percebemos que a metodologia adotada pelo aluno não foi adequada.

O exemplo anterior mostrou um caso acadêmico, no qual quem mantinha o documento era apenas o aluno, posteriormente será abordado casos no mercado de trabalho, no qual o trabalho será realizado em equipe, mas antes disso é necessário entender a estrutura do Git.

Estrutura do Git

Utilizando adaptações das definições da documentação da Microsoft.

Repositório

Também é conhecido como repo, é a maior unidade de armazenamento. Um repositório contém uma ou mais branches.

Branch (Ramificação)

Uma unidade de armazenamento que contém os arquivos e as pastas que compõem o conjunto de conteúdo de um projeto.

As branches separam fluxos de trabalho (normalmente conhecidos como versões). As contribuições sempre são feitas para uma branch específica e estará naquele escopo.

Todos os repositórios contêm uma ramificação padrão (normalmente chamada “master") e uma ou mais ramificações que serão mescladas novamente na ramificação padrão.

A ramificação padrão funciona como a versão atual e é “única fonte de verdade” para o projeto. Ela é a mãe e todos as outras branches no repositório são criados a partir dela.

A aparência das ramificações é a seguinte:

Git em diversos setores de trabalho

Utilizando adaptações do material da Atlassian “Why Git for your organization".

Git para desenvolvedores

Fluxo de trabalho

Desenvolvimento distribuído

Solicitações de inserção

Ciclo de lançamento mais rápido

Git para marketing

Git para gerenciamento de produto

Git para designers

Um extra…

Git para administradores de infraestrutura

Instalando o Git

Se estiver em um ambiente Windows, recomendo utilizar o Chocolatey para instalar o Git:

bash
$ choco install git $

Se estiver em um ambiente Mac, recomendo utilizar o Homebrew para instalar o Git:

bash
$ brew install git $

Se estiver em um ambiente baseado Linux baseado no Debian:

bash
$ sudo apt install git $

Para verificar se o Git foi instalado:

A versão ser diferente não é um problema

bash
$ git --version git version 2.25.1 $

Configuração inicial

Se estiver usando um ambiente Windows, utilize o Git Bash que foi instalado em conjunto com o Git.

Configurando usuário

bash
$ git config --global user.name "Seu Nome" $ git config --global user.email "seu-email@email.com" $

Primeiros passos

Criação do repositório

bash
repo$ git init repo $ cd repo $

Verificação da criação do repositório

bash
repo$ ls -A .git $

Criando um arquivo

bash
repo$ echo "Olá Mundo" > arquivo.txt $

Verificação da criação do arquivo

bash
repo$ cat arquivo.txt Olá Mundo $

Ciclo de vida dos arquivos

Untracked

O Git não está controlando o ciclo de vida deste arquivo

bash
repo$ git status -s ?? arquivo.txt $

Staged

O arquivo fará parte parte do próximo commit

bash
repo$ git add arquivo.txt $ git status -s A arquivo.txt $

Unmodified

O arquivo já foi “commitado” e não foi modificado

bash
repo$ git commit -m "Primeiro commit" $ git status -s $

Modified

O arquivo já foi “commitado” e foi modificado

bash
repo$ echo "Nova Linha" >> arquivo.txt $ git status -s M arquivo.txt $

Para visualizar as modificações podemos usar o git diff:

bash
repo$ git diff arquivo.txt Olá Mundo +Nova Linha $

Realizando um commit

Adicionando outro arquivo

bash
repo$ touch outro-arquivo.txt $ git status -s M arquivo.txt ?? outro-arquivo.txt $

git add

  • git add -u: Apenas arquivos monitorados

  • git add .: Todos os arquivos (diretório e subdiretórios)

  • git add -A: Todos os arquivos (toda a árvore de trabalho)

bash
repo$ git add -A $ git status -s M arquivo.txt A outro-arquivo.txt $

git commit

  • git commit -m “descrição”: Descrições menos detalhadas

  • git commit: Descrições mais detalhadas

bash
repo$ git commit -m "Segundo Commit" $

Se quisermos alterar o ultimo commit:

bash
repo$ git commit --amend -m "Segundo commit" $

git log

bash
repo$ git log --oneline as1209d (HEAD -> master) Segundo commit qw3487e Primeiro commit $ git log --pretty=format:"%h | %an - %ar: %s" as1209d | Seu Nome - 2 minutes ago: Segundo commit qw3487e | Seu Nome - 7 minutes ago: Primeiro commit $ git log --oneline --since=5.minutes as1209d (HEAD -> master) Segundo commit $ git log --oneline --stat as1209d (HEAD -> master) Segundo commit arquivo.txt | 1 + outro-arquivo.txt | 0 2 files changed, 1 insertion(+) qw3487e Primeiro commit arquivo.txt | 1 + 1 file changed, 1 insertion(+) $

Ignorando arquivos

Criando o .gitignore

bash
repo$ touch file.log $ git status -s ?? file.log $ echo '*.log' > .gitignore $ git status -s ?? .gitignore $ git add .gitignore $ git commit -m "Ignorando *.log" $

Ignorando arquivos já “commitados”

bash
repo$ git rm --cached outro-arquivo.txt $ git status -s D outro-arquivo.txt ?? outro-arquivo.txt $ echo outro-arquivo.txt >> .gitignore $ git status -s M .gitignore D outro-arquivo.txt $ git commit -am "Ignorando outro-arquivo.txt" $

Depurar o .gitignore

bash
repo$ git check-ignore -v file.log .gitignore:1:*.log file.log $

Desfazendo alterações

Restaurar arquivos da árvore de trabalho

bash
repo$ echo "Outra linha" >> arquivo.txt $ cat arquivo.txt Olá Mundo Nova Linha Outra linha $ git restore arquivo.txt $ cat arquivo.txt Olá Mundo Nova Linha $

Mudando para um commit específico

bash
repo$ git log --oneline lk1209j (HEAD -> master) Ignorando outro-arquivo.txt po3487i Ignorando secret.txt as1209d Segundo commit qw3487e Primeiro commit $ git checkout qw3487e $ git log --oneline qw3487e (HEAD) Primeiro commit $ git checkout master $ git log --oneline lk1209j (HEAD -> master) Ignorando outro-arquivo.txt po3487i Ignorando secret.txt as1209d Segundo commit qw3487e Primeiro commit $

git reset

  • git reset –soft: Desfaz Commit. Mantem Stage e modificações

  • git reset –mixed: Desfaz Commit e Stage. Mantém modificações [Padrão]

  • git reset –hard: Desfaz Commit, Stage e modificações

bash
repo$ git reset HEAD~2 --hard $ git log --oneline as1209d (HEAD -> master) Segundo commit qw3487e Primeiro commit $

git revert

bash
repo$ git revert --no-commit HEAD repo$ git commit -m "Revertendo para o primeiro commit" $ git log --oneline mn2356b (HEAD -> master) Revertendo para o primeiro commit as1209d Segundo commit qw3487e Primeiro commit $

git reflog

Reflogs rastreiam quando refs Git foram atualizados no repositório local.

Utilizando branches

Criando uma branch

bash
repo$ git branch outra-branch $ git branch * master outra-branch $

Deletando uma branch

bash
repo$ git branch -d outra-branch $ git branch * master $

Alterar branch

Para criar uma branch, utilizar a flag -c.

bash
repo$ git switch -c outra-branch $ git branch master * outra-branch $ git log --oneline mn2356b (HEAD -> outra-branch, master) Revertendo para o primeiro commit as1209d Segundo commit qw3487e Primeiro commit $

Realizando commits na branch

bash
repo$ echo "Modificação 1" >> arquivo.txt $ git commit -am "Modificação 1" repo$ echo "Modificação 2" >> arquivo.txt $ git commit -am "Modificação 2" repo$ echo "Modificação 3" >> arquivo.txt $ git commit -am "Modificação 3" $ cat arquivo.txt Olá Mundo Modificação 1 Modificação 2 Modificação 3 $ git log --oneline mnb2468 (HEAD -> outra-branch) Modificação 3 asd1357 Modificação 2 qwe4680 Modificação 1 mn2356b (master) Revertendo para o primeiro commit as1209d Segundo commit qw3487e Primeiro commit $

git merge

Fast-forward

bash
repo$ git switch master $ git merge outra-branch Fast-forward arquivo.txt | 3 +++ 1 file changed, 3 insertions(+) $ git log --oneline mnb2468 (HEAD -> master, outra-branch) Modificação 3 asd1357 Modificação 2 qwe4680 Modificação 1 mn2356b Revertendo para o primeiro commit as1209d Segundo commit qw3487e Primeiro commit $

No Fast-forward

bash
repo$ git reset --hard HEAD~3 $ echo "Modificação master" >> arquivo.txt $ git commit -am "Modificação master" $ git merge outra-branch CONFLICT (content): Merge conflict in arquivo.txt $ sed -i '/^<<<<<<</d' arquivo.txt $ sed -i '/^=======/d' arquivo.txt $ sed -i '/^>>>>>>>/d' arquivo.txt $ git commit -am "Merge da branch outra-branch" $ git log --oneline --graph * 05d44f5 (HEAD -> master) Merge da branch outra-branch |\ | * mnb2468 (outra-branch) Modificação 3 | * asd1357 Modificação 2 | * qwe4680 Modificação 1 * | pu1234o Modificação master |/ * mn2356b Revertendo para o primeiro commit * as1209d Segundo commit * qw3487e Primeiro commit $

git rebase

bash
repo$ git reset --hard HEAD~1 $ git rebase outra-branch CONFLICT (content): Merge conflict in arquivo.txt $ sed -i '/^<<<<<<</d' arquivo.txt $ sed -i '/^=======/d' arquivo.txt $ sed -i '/^>>>>>>>/d' arquivo.txt $ git add arquivo.txt $ git rebase --continue $ git log --oneline --graph * pu1234o (HEAD -> master) Modificação master * mnb2468 (outra-branch) Modificação 3 * asd1357 Modificação 2 * qwe4680 Modificação 1 * mn2356b Revertendo para o primeiro commit * as1209d Segundo commit * qw3487e Primeiro commit $

Tags

Adicionando uma tag

Para adicionar uma mensagem, utilizar a flag -m

bash
repo$ git tag 1.0.0 $

Deletando uma tag

bash
repo$ git tag -d 1.0.0 $

Armazenando mudanças

git stash

  • git stash: Apenas os arquivos monitorados

  • git stash -u:: Inclui também os arquivos não monitorados

  • git stash -a:: Inclui também os arquivos não monitorados e ignorados

Primeiro armazenamento

bash
repo$ echo "Olá Mundo" > arquivo.txt $ git status -s M arquivo.txt $ git stash $ git status -s $ git stash list stash@{0}: WIP on master: mnb2468 Modificação 3 $

git stash apply

bash
repo$ git switch outra-branch $ git stash apply $ git status -s M arquivo.txt $ cat arquivo.txt Olá Mundo $ git stash list stash@{0}: WIP on master: mnb2468 Modificação 3 $

git stash pop

bash
repo$ git restore arquivo.txt $ git switch master $ git stash pop $ git stash list $ git status -s M arquivo.txt $

git stash save

bash
repo$ git stash save "Modificação arquivo.txt" $ git stash list stash@{0}: On master: Modificação arquivo.txt $

git stash show

bash
repo$ git stash show arquivo.txt | 3 --- 1 file changed, 3 deletions(-) $

git stash -p

bash
repo$ git stash pop stash@{0} $ git stash -p $

git stash branch

bash
repo$ git stash branch stash-branch stash@{0} $ git branch master outra-branch * stash-branch $ git switch master $ git branch -d stash-branch $ git status -s M arquivo.txt $

git stash drop

bash
repo$ git stash save "Modificação 1" $ echo "Olá Mundo 2" > arquivo.txt $ git stash save "Modificação 2" $ git stash list stash@{0}: On master: Modificação 2 stash@{1}: On master: Modificação 1 $ git stash drop stash@{0} $ git stash list stash@{0}: On master: Modificação 1 $

git stash clear

bash
repo$ git stash clear $ git stash list $

Git bare

bash
repo$ mkdir ../repo.git $ git init --bare ../repo.git $ git remote add local full/path/to/repo.git $

Git hook

bash
repo$ cat > ../repo.git/hooks/post-receive << EOF #!/bin/sh git --work-tree=/var/www/html checkout -f EOF $ chmod +x ../repo.git/hooks/post-receive $ git mv arquivo.txt index.html $ echo "<h1>Git</h1>" > index.html $ git commit -am "Página html" $ git push local master $ curl localhost <h1>Git</h1> $

Chaves SSH

Algoritmo ed25519

bash
$ ssh-keygen -t ed25519 -a 128 -C "Comentário" $

Algoritmo rsa

Usar se o algoritmo ed25519 não for suportado

bash
$ ssh-keygen -t rsa -b 4096 -o -a 128 -C "Comentário" $

O objetivo dessa seção foi mostrar como gerar chaves SSH seguras, para mais informações veja o artigo do GitHub About SSH.

Instalando o Git Flow

Se estiver em um ambiente Windows, o Git Flow já estará instalado, ele foi incluído na versão 2.5.3 do Git for Windows.

Se estiver em um ambiente Mac, recomendo utilizar o Homebrew para instalar o Git Flow:

bash
$ brew install git-flow $

Se estiver em um ambiente baseado Linux baseado no Debian:

bash
$ sudo apt install git-flow $

Para verificar se o Git Flow foi instalado:

A versão ser diferente não é um problema

bash
$ git flow version 1.12.3 (AVH Edition) $

Entendendo o Git Flow

O Git Flow é um fluxo de trabalho para o Git, criado por Vincent Driessen, a partir da sua publicação A successful Git branching model no ano de 2010.

Utilizando o Git Flow

Inicializar um repositório

bash
$ mkdir flow $ cd flow flow$ git flow init $

Features (Funcionalidades)

Começar uma funcionalidade

bash
flow$ git flow feature start minha-feature $

Finalizar uma funcionalidade

bash
flow$ git flow feature finish minha-feature $

Publicar uma funcionalidade

bash
flow$ git flow feature publish minha-feature $

Obter uma funcionalidade publicada

bash
flow$ git flow feature pull minha-feature $

Releases (Versões)

Começar uma versão

bash
flow$ git flow release start minha-versao $

Publicar um versão

bash
flow$ git flow release publish minha-versao $

Finalizar uma versão

bash
flow$ git flow release finish minha-versao $

Hotfixes

Começar uma hotfix

bash
flow$ git flow hotfix start minha-hotfix $

Finalizar uma hotfix

bash
flow$ git flow hotfix finish minha-hotfix $

Contatos

https://github.com/GaMoCh

https://linkedin.com/in/gabrielmchaves