Treinamento sobre Git

Capítulo 1

Introdução e Conceitos

Introdução e Conceitos

Gerenciamento de Configuração

Processo de engenharia de sistemas para estabelecer a consistência dos atributos de um produto ao longo da vida dele. (...) Processo de gerenciamento de TI que monitora itens de configuração individuais de um sistema de TI.
Gerenciamento de configuração: definição e benefícios (Atlassian)

Introdução e Conceitos

Gerenciamento de Configuração

Principais benefícios:

  • Controle efetivo de versões
  • Rastreabilidade das mudanças
  • Colaboração em equipe
  • Melhoria da qualidade do código
  • Facilidade de recuperação em caso de problemas

Introdução e Conceitos

Controle de Versão

Sistemas de Versionamento de Código (em inglês: "Version Control System" ou VCS) são serviços responsáveis por controlar modificações e diferentes versões do código de nossos sistemas, fornecendo histórico para alterações, trabalho em equipe e separação do ambiente de trabalho entre colaboradores

Conceitos Fundamentais de Controle de Versão

Tipos de Controle de Versão

Centralizado

Um servidor central é responsável por receber todas as modificações dos colaboradores

Toda alteração feita na máquina é automaticamente enviada ao servidor central

Vários metadados ficam apenas no servidor principal, acarretando em um único ponto de falha

Distribuído

Mesmo havendo um servidor principal, os colaboradores possuem suas cópias offline que podem servir inclusive como backup

As alterações são primeiro realizadas na cópia local do servidor e, depois, devem ser enviadas para o servidor principal pelo colaborador

Why you should move from centralized version control to distributed version control (GitLab.com)

Conceitos Fundamentais de Controle de Versão

Ferramentas de Controle de Versão

Alguns dos principais Sistemas de Controle de Versão são:

History of Version Control Systems VCS (dev.to)

Introdução e Conceitos

Git

Ferramenta criada por Linus Torvalds (o criador do Linux) em 2005, após a licença do BitKeeper se tornar paga, impossibilitando seu uso no Linux

BitKeeper and Linux: The end of the road?

Introdução e Conceitos

Git

Palestra do Linus Torvalds sobre git em 2007

Introdução e Conceitos

Git

Principais conceitos

The development of Git began on 3 April 2005. Torvalds announced the project on 6 April and became self-hosting the next day. The first merge of multiple branches took place on 18 April. Torvalds achieved his performance goals; on 29 April, the nascent Git was benchmarked recording patches to the Linux kernel tree at a rate of 6.7 patches per second. On 16 June, Git managed the kernel 2.6.12 release. Torvalds turned over maintenance on 26 July 2005 to Junio Hamano, a major contributor to the project. Hamano was responsible for the 1.0 release on 21 December 2005.
Git (Wikipedia)

Introdução e Conceitos

Visão Geral do GitHub

  • Plataforma criada em 2008 para hospedagem e gerenciamento de repositórios Git, colaboração em projetos, controle de versões, integração contínua, e muito mais.
  • É uma das maiores comunidades de desenvolvedores do mundo, facilitando o trabalho em equipe e o compartilhamento de código aberto.
  • Possui planos gratuitos e pagos, com recursos avançados para equipes e empresas.
  • Disponível como SaaS (Software-as-a-Service), mas também pode ser utilizado em ambientes privados com o GitHub Enterprise.
Features | GitHub

Capítulo 2

Introdução e Conceitos (cont.)
Controle de Versão com Git

Introdução e Conceitos

Conceitos gerais

Repositório

Entidade básica do versionamento, contemplando todas as versões do código, branches, tags e parâmetros de configuração do projeto que serão lidos pelo git (como quais arquivos devem ser ignorados e mantidos)

Plataformas como o Github oferecem mais recursos para facilitar a manutenção do projeto, como:

  • Automações de segurança;
  • Esteiras de CI/CD;
  • Gestão de problemas através de "issues";
  • Revisão para aprovações de mudanças (merge requests);
  • Wikis para manter a documentação do projeto;
  • Entre muitos outros.

Introdução e Conceitos

Conceitos gerais

Branch

Ramificações do repositório, possibilitando criar "cópias" do código para podermos trabalhar em atividades diferentes da nossa aplicação ao mesmo tempo, como resolução de bugs ou criação de novas funcionalidades

Introdução e Conceitos

Conceitos gerais

Diff

Comparação entre dois arquivos para encontrar as mudanças entre os dois, sendo uma forma de representar alterações incrementais em um sistema

Imagine então que...

  • Existe uma aplicação de terceiros chamada minha-aplicacao
  • Você gostaria de alterar algo em um arquivo build
  • Você precisa enviar essas mudanças para que o mantenedor as incorpore
  • É possível fazer isso com os comandos diff e patch do Unix, sem precisar de sistemas de controle de versão!

                            $ diff -ruN minha-aplicacao/ > mudancas.path
                            $ patch -p0 < mudancas.patch
                        

Introdução e Conceitos

Conceitos gerais

Commit

Conjunto de diffs de arquivos distintos, acompanhado de metadados para identificar o autor daquela ação, a data em que foi realizada e uma mensagem explicando o que foi feito

No git, todo commit é representando por um hash SHA-1, que leva em consideração todos os metadados descritos acima, as alterações realizadas e o hash do commit anterior ("pai"), garantindo assim a integridade daquela ação


                            32b3b430c8bf4b029422f82f164330cd91a9a2e3
                        
The Git Commit Hash

Introdução e Conceitos

Conceitos gerais

Merge

Processo de mesclar uma branch em outra, incorporando os commits realizados na branch de origem em uma outra

É feito geralmente quando terminamos o desenvolvimento de uma funcionalidade ou correção de bugs em uma branch e queremos trazer o código para a principal (por exemplo, a main)

Fluxo de merge no Git

Introdução e Conceitos

Conceitos gerais

Tag

Marcação que aponta para um determinado commit, sendo normalmente utilizada para demarcar as versões da sua aplicação

Podem receber qualquer nome (por exemplo, versao-inicial ou alteracao-para-o-novo-layout), mas geralmente utilizamos Versionamento Semântico para identificar as versões mais facilmente

Tags no Git

Introdução e Conceitos

Conceitos gerais

Staging

Área em que arquivos são adicionados para indicar que estão preparados para serem incluídos no commit

Controle de Versão com Git

Controle de Versão com Git

Instalando o git

Instruções de instalação do git para cada Sistema Operacional:

  • Linux
  • Mac
  • Windows
    • Sugiro a versão Standalone Installer (e provavelmente deve ser 64-bit Git for Windows Setup)
git-scm.com

Controle de Versão com Git

Comandos básicos

git init

Inicializa o diretório atual para ser utilizado como repositório, criando a pasta .git

Documentação oficial: git init

git remote

Gerencia os endereços dos servidores remotos para atualização e sincronização do repositório

Documentação oficial: git remote

Controle de Versão com Git

Comandos básicos

git clone

Processo de fazer o "download" de um repositório para trabalhar em sua cópia local, também sendo reconhecido pelo termo em inglês de checkout

Documentação oficial: git clone

No Github (e em outras plataformas), pode ser feito através dos protocolos HTTP e SSH

Clonando um repositório | GitHub Docs

Controle de Versão com Git

Comandos básicos

git config

Gerencia diversas configurações do seu git, podendo alterar parâmetros globais (que se aplicam a todos os repositórios que você possui em sua máquina) ou exclusivamente no repositório de onde está executando o comando


                            $ git config --global user.name "Seu nome"
                            $ git config --global user.email "seu-email-do-github@exemplo.com"
                        
Git Configuration

Controle de Versão com Git

Comandos básicos

git status

Mostra o estado da árvore de trabalho ("working tree"), exibindo arquivos que foram adicionados, modificados ou excluídos

Também mostra arquivos que estão na área de staging, prontos para participarem do commit, e os que ainda não estão sendo "rastreados"


                            $ git status
                            On branch main
                            Changes to be committed:
                              (use "git restore --staged <file>..." to unstage)
                                modified:   arquivo/que/foi/adicionado/ao/staging

                            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:   arquivo/modificado/que/nao/esta/no/staging

                            Untracked files:
                              (use "git add <file>..." to include in what will be committed)
                                arquivo/nao/adicionado
                        
Documentação oficial: git status

Controle de Versão com Git

Comandos básicos

git add

Adiciona arquivos (ou diretórios) para a área de staging


                            $ git status
                            On branch main

                            No commits yet

                            nothing to commit (create/copy files and use "git add" to track)

                            $ touch novo-arquivo

                            $ git add novo-arquivo

                            $ git status
                            On branch main

                            No commits yet

                            Changes to be committed:
                              (use "git rm --cached <file>..." to unstage)
                                new file:   novo-arquivo
                        
Documentação oficial: git add

Controle de Versão com Git

Comandos básicos

git commit

"Captura" os arquivos que estão na área de staging em um pacote que poderá ser enviado ao servidor remoto posteriormente

É possível adicionar todos os arquivos da área de staging ou apenas alguns deles

Se não especificarmos o parâmetro -m "mensagem do commit" para informar a mensagem, um editor de texto será aberto para que possamos fornecê-la

Documentação oficial: git commit

Controle de Versão com Git

Comandos básicos

git log

Mostra o histórico de commits naquele branch ou de um arquivo específico

Documentação oficial: git log

Controle de Versão com Git

Comandos básicos

git push

Envia os commits que estão no repositório local para o servidor remoto

Documentação oficial: git push

Capítulo 3

Controle de Versão com Git (cont.)

Controle de Versão com Git

Comandos básicos

git mv

Move ou renomeia um arquivo da cópia de trabalho

Documentação oficial: git mv

Controle de Versão com Git

Comandos básicos

git rm

Remove um arquivo da cópia de trabalho

Documentação oficial: git rm

Controle de Versão com Git

Comandos básicos

git diff

Mostra as diferenças entre os arquivos atuais e o que está no servidor remoto ou entre commits

Documentação oficial: git diff

Controle de Versão com Git

Comandos básicos

git show

Exibe detalhes de um commit, tag ou de um arquivo específico

Documentação oficial: git show

Controle de Versão com Git

Comandos básicos

git fetch

Atualiza os metadados do repositório a partir do servidor remoto

Documentação oficial: git fetch

Controle de Versão com Git

Comandos básicos

git pull

Atualiza os metadados do repositório (como o git fetch) e atualiza sua cópia local com as alterações da branch especificada (como o git merge, que veremos nas aulas a seguir)

Documentação oficial: git pull

Controle de Versão com Git

Comandos intermediários

git --help

Todos os comandos do git possuem um parâmetro --help para mostrar mais detalhes sobre como podemos usá-los!

Documentação oficial: git

Controle de Versão com Git

Comandos intermediários

git log

Já vimos como usá-lo de forma mais simples, mas existem diversos argumentos para consultarmos o histórico de alterações

Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para consultar apenas os commits que envolvem um determinado arquivo, utilize o parâmetro --follow:


                            $ git log --follow -- <arquivo>
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para ter uma visão mais compacta, podemos usar o parâmetro --oneline:


                            $ git log --oneline
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para saber os arquivos modificados, utilize --stat:


                            $ git log --stat
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para procurar os commits de um único autor, utilize --author:


                            $ git log --author "Parte do nome ou email do autor"
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para retornar apenas os commits após uma certa data, utilize --after:


                            $ git log --after "2023-01-01"
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para retornar apenas os commits antes de uma certa data, utilize --before:


                            $ git log --before "2023-01-01"
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para buscar apenas os commits que possuem certa mensagem, utilize --grep:


                            $ git log --grep "Parte da mensagem"
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para buscar commits que possuem uma certa string de código que foi adicionada ou excluída, utilize -S:


                            $ git log -S "console.log"
                        

Isso irá mostrar todos os commits em que houveram adições ou exclusões do texto console.log

Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para buscar commits que possuem uma certa string de código que foi adicionada, excluída ou modificada, utilize -G:


                            $ git log -G "console.log"
                        

Isso irá mostrar todos os commits em que houveram adições, exclusões ou modificações do texto console.log

Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para visualizar de forma gráfica os commits, branches e merges do repositório, utilize --graph:


                            $ git log --graph
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git log

Para buscar apenas alterações entre as linhas 50 e 100 de um arquivo index, execute:


                            $ git log -L 50,100:index
                        
Documentação oficial: git log

Controle de Versão com Git

Comandos intermediários

git shortlog

Forma de visualizar o histórico do git log de uma forma mais simples

Documentação oficial: git shortlog

Controle de Versão com Git

Comandos intermediários

git blame

Saiba qual foi a última modificação em cada linha do arquivo

Documentação oficial: git blame

Capítulo 4

Controle de Versão com Git (cont.)

Controle de Versão com Git

Comandos intermediários

git checkout

Altera a branch em que você está trabalhando, cria uma nova branch ou restaura um arquivo a partir da branch informada

Documentação oficial: git checkout

Controle de Versão com Git

Comandos intermediários

git branch

Lista, cria ou exclui branches, podendo também mostrar as que contém ou não determinado commit

Documentação oficial: git branch

Controle de Versão com Git

Comandos intermediários

git branch

Para excluir um branch que está apenas na sua cópia local:


                            $ git branch -d nome-do-branch   # Isso exclui apenas branches que já foram "mergeados"
                            $ git branch -D nome-do-branch   # Para excluir branches que ainda não foram "mergeados"
                        
Documentação oficial: git branch

Controle de Versão com Git

Comandos intermediários

git branch

Para excluir um branch do servidor remoto:


                            $ git push -d origin nome-do-branch
                        
Documentação oficial: git branch

Controle de Versão com Git

Configuração de um Projeto no GitHub

Vamos ver algumas configurações possíveis para gerenciamento dos projetos no GitHub:

  • Arquivos README;
  • Criação de Wikis;
  • Criação de Issues;
  • Abertura e resoluções de Pull requests;
  • Entre outros.

Capítulo 5

Fluxos de Trabalho

Fluxos de Trabalho

Para facilitar a colaboração entre pessoas diferentes em um mesmo repositório, é recomendado o seguinte fluxo para uso do git no dia-a-dia:

  1. Antes de criar uma funcionalidade ou corrigir um bug, crie uma branch e trabalhe nela
  2. Após terminar o desenvolvimento, abra um merge request para que outras pessoas possam avaliar aquele código (code review) e realizar os devidos testes
    • Se forem requisitadas mudanças, altere o código e peça uma nova avaliação
    • Ao ser aprovado, você ou o mantenedor do repositório deve realizar o merge na branch principal (main)
  3. A branch principal (main) possui códigos que estão prontos para serem publicados em produção ou disponibilizados para os clientes

Fluxos de Trabalho

Git Flow

Lançado em 2010, tem sido desencorajado para a grande maioria dos projetos, a não ser para os que trabalham com datas fixas para o lançamento de cada versão

  • Possui duas branches principais: main e develop
  • Para cada nova funcionalidade ou correção de bugs, devemos criar uma branch a partir de develop, que será mesclada de volta ao fim do desenvolvimento
  • Ao se aproximar da data de lançamento (ou quando houver conteúdo o suficiente para uma nova versão), uma nova branch chamada release será criada a partir da develop
  • A partir desse momento, a branch develop não deve conter novos recursos, apenas correções de segurança, melhorias de implementação ou documentação
  • Quando tudo estiver pronto, fazemos o merge do release para a main

Fluxos de Trabalho

Git Flow

Exemplo:

Exemplo do Git Flow
  • Na main, temos a versão atual
  • Criamos a branch develop a partir da v1.0
  • Para cada desenvolvimento, criamos uma nova branch a partir da develop
  • Ao terminar cada desenvolvimento, fazemos o merge para a develop
  • Na data de congelamento do release, paramos de aceitar novas funções e criamos a branch release
  • Apenas correções e melhorias serão aceitas
  • Quando tudo estiver testado e aceito, fazemos o merge da release para a main e geramos uma nova versão para publicar

Fluxos de Trabalho

GitHub Flow

Mais simples que o Git Flow, permite a publicação do software sempre que terminamos o desenvolvimento de uma funcionalidade ou correção de bug

Para isso, é primordial termos configurado esteiras de CI/CD para testar e integrar as alterações do sistema (que veremos em breve)

GitHub Flow

Gerenciamento de Branches

Gerenciamento de Branches

Merging

O merge é utilizado quando queremos incorporar todas as modificações efetuadas em uma branch em uma outra

Gerenciamento de Branches

Merging

git merge

Faz a incorporação de uma branch em outra, podendo "achatar" todos os commits em um só através do parâmetro --squash

Fluxo de merge no Git Documentação oficial: git merge

Gerenciamento de Branches

Resolução de Conflitos

Ao executarmos o git merge, se alguma das branches possuir modificações nas mesmas linhas de um arquivo (ou se uma branch editou um arquivo e a outra o removeu), o git irá exibir uma mensagem de conflito, pois não sabe qual dessas modificações deve aplicar

Conflitos no merge

Gerenciamento de Branches

Resolução de Conflitos


                            $ git merge develop
                            Auto-merging README
                            CONFLICT (content): Merge conflict in README
                            Automatic merge failed; fix conflicts and then commit the result.

                            $ git status
                            On branch main
                            You have unmerged paths.
                              (fix conflicts and run "git commit")
                              (use "git merge --abort" to abort the merge)

                            Unmerged paths:
                              (use "git add/rm <file>..." to mark resolution)
                                both modified:   README
                        

Gerenciamento de Branches

Resolução de Conflitos

Ao abrir o arquivo com conflitos em um editor de textos, você verá marcações como essas:


                            Linha 1
                            <<<<<<< HEAD
                            Linha 2 <-- alterando linha 2 na main
                            =======
                            Linha 2 <-- alterado na develop
                            >>>>>>> develop
                            Linha 3
                        

Essas marcações ao redor das linhas "Linha 2" indicam os blocos com alterações conflitantes:

  • O primeiro bloco, que começa em <<<<<<< e vai até =======, mostra o que temos atualmente no HEAD
  • O segundo bloco (entre o mesmo ======= até o próximo >>>>>>>) nos informa o que está vindo da develop

Gerenciamento de Branches

Resolução de Conflitos

Para resolver o conflito manualmente, devemos resolver todo o código entre <<<<<<< e >>>>>>>, removendo essas marcações


                            Linha 1
                            <<<<<<< HEAD
                            Linha 2 <-- alterando linha 2 na main
                            =======
                            Linha 2 <-- alterado na develop
                            >>>>>>> develop
                            Linha 3
                        

Gerenciamento de Branches

Resolução de Conflitos

Para resolver o conflito manualmente, devemos resolver todo o código entre <<<<<<< e >>>>>>>, removendo essas marcações


                            Linha 1
                            Linha 2 <-- mesclando alterações da main e da develop
                            Linha 3
                        

Gerenciamento de Branches

Resolução de Conflitos

Pode se tornar difícil resolver esses conflitos manualmente, então dê preferência a resolvê-los com algumas ferramentas:

Capítulo 6

Controle de Versão com Git (cont.)
Incorporando Mudanças

Controle de Versão com Git

Mais comandos

git tag <nome-da-tag>

Marcação que aponta para um determinado commit, sendo normalmente utilizada para demarcar as versões da sua aplicação

Podem receber qualquer nome (por exemplo, versao-inicial ou alteracao-para-o-novo-layout), mas geralmente utilizamos Versionamento Semântico para identificar as versões mais facilmente


                                    $ git commit -m 'Meu primeiro commit'
                                    $ git tag v1.0.0
                                    $ git log --oneline
                                    be598a0 (HEAD -> main, tag: v1.0.0) Meu primeiro commit
                                
Tags no Git

Controle de Versão com Git

Mais comandos

git checkout <commit-ou-tag>

Altera o estado para um commit específico


                            $ git log --oneline
                            f5c16a7 (HEAD -> main) Meu segundo commit
                            be598a0 (tag: v1.0) Meu primeiro commit

                            $ git checkout be598a0
                            Note: switching to 'be598a0'.

                            $ git status
                            HEAD detached at be598a0
                        

Controle de Versão com Git

Mais comandos

git restore

Desfaz as modificações em um arquivo, revertendo à versão do último commit


                            $ git status
                            On branch main
                            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:   arquivo

                            no changes added to commit (use "git add" and/or "git commit -a")

                            $ git restore arquivo

                            $ git status
                            On branch main
                            nothing to commit, working tree clean
                        

Controle de Versão com Git

Mais comandos

git restore --staged

Retira um arquivo da área de staging


                            $ git add arquivo

                            $ git status
                            On branch main
                            Changes to be committed:
                              (use "git restore --staged <file>..." to unstage)
                                modified:   arquivo

                            $ git restore --staged arquivo

                            $ git status
                            On branch main
                            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:   arquivo

                            no changes added to commit (use "git add" and/or "git commit -a")
                        

Controle de Versão com Git

Mais comandos

git reset <referência>

Traz todo o estado do commit especificado para o projeto atual, mantendo as modificações locais


                            $ git log --oneline
                            9581191 (HEAD -> main) Versão nova
                            5287db4 Versão antiga

                            $ git reset 5287db4
                            Unstaged changes after reset:
                            M    arquivo

                            $ git log --oneline
                            5287db4 (HEAD -> main) Versão antiga
                        

Controle de Versão com Git

Mais comandos

git reset --hard <referência>

Traz todo o estado do commit especificado para o projeto atual, descartando as modificações locais


                            $ git log --oneline
                            9581191 (HEAD -> main) Versão nova
                            5287db4 Versão antiga

                            $ git reset --hard 5287db4
                            HEAD is now at 5287db4 Versão antiga

                            $ git log --oneline
                            5287db4 (HEAD -> main) Versão antiga

                            $ git status
                            On branch main
                            nothing to commit, working tree clean
                        

Controle de Versão com Git

Mais comandos

git revert <hash-do-commit>

Ao invés de descartar os commits, esse comando cria um outro commit com as alterações "reversas"

Ou seja: linhas que foram adicionadas serão removidas, as que foram removidas serão adicionadas de volta, arquivos que foram criados serão excluídos, etc...


                            $ git log --oneline
                            7d4abd6 (HEAD -> main) Mudanças do arquivo

                            $ git show 7d4abd6 --oneline
                            7d4abd6 Mudanças do arquivo
                            diff --git a/arquivo b/arquivo
                            index 7898192..3dcb048 100644
                            --- a/arquivo
                            +++ b/arquivo
                            @@ -1 +1 @@
                            -Versão anterior
                            +Mudanças do arquivo
                        

Controle de Versão com Git

Mais comandos

git revert <hash-do-commit>

Ao invés de descartar os commits, esse comando cria um outro commit com as alterações "reversas"

Ou seja: linhas que foram adicionadas serão removidas, as que foram removidas serão adicionadas de volta, arquivos que foram criados serão excluídos, etc...


                            $ git revert 7d4abd6
                            [main 26b83e6] Revert "Mudanças do arquivo"
                            1 file changed, 1 insertion(+), 1 deletion(-)

                            $ git log --oneline
                            26b83e6 (HEAD -> main) Revert "Mudanças do arquivo"
                            7d4abd6 Mudanças do arquivo

                            $ git show 26b83e6 --oneline
                            26b83e6 (HEAD -> main) Revert "Mudanças do arquivo"
                            diff --git a/arquivo b/arquivo
                            index 3dcb048..7898192 100644
                            --- a/arquivo
                            +++ b/arquivo
                            @@ -1 +1 @@
                            -Mudanças do arquivo
                            +Versão anterior
                        

Controle de Versão com Git

Incorporando Mudanças

git merge <nome-da-branch>

Exercício

Pessoa 1

  • Crie uma branch do repositório, altere algo e faça commit e push
  • Aguarde a Pessoa 2 fazer o trabalho dela
  • Incorpore as mudanças da Pessoa 2 executando git fetch e git merge branch-da-pessoa-2
  • Faça o push da sua branch

Pessoa 2

  • Crie uma branch do repositório, altere algo diferente da Pessoa 1 e faça commit e push
  • Avise a Pessoa 1 que você terminou

Controle de Versão com Git

Incorporando Mudanças

git cherry-pick <referência>

Busca um commit exato e traz para a sua branch


                            $ git log --oneline
                            91e2609 (HEAD -> branch1) Estou na branch 1

                            $ git cherry-pick 7d9af37

                            $ git log --oneline
                            236b1fc (HEAD -> branch1) Mudanças no arquivo na branch2
                            91e2609 Estou na branch 1

                        

Controle de Versão com Git

Incorporando Mudanças

git cherry-pick <referência>

Exercício

Pessoa 1

  • Crie uma branch do repositório, altere algo e faça commit e push
  • Aguarde a Pessoa 2 fazer o trabalho dela
  • Incorpore as mudanças da Pessoa 2 executando git fetch e git cherry-pick <hash-do-commit>
  • Faça o push da sua branch

Pessoa 2

  • Crie uma branch do repositório, altere algo diferente da Pessoa 1 e faça commit e push
  • Avise a Pessoa 1 que você terminou

Capítulo 7

Incorporando Mudanças (cont.)
Github: funcionalidades e fork

Controle de Versão com Git

Incorporando Mudanças

git rebase <nome-da-branch>

"Move" o início da sua branch para outro lugar no histórico de commits, útil para trazer as modificações da main, por exemplo

Branch pré-rebase

Controle de Versão com Git

Incorporando Mudanças

git rebase <nome-da-branch>

"Move" o início da sua branch para outro lugar no histórico de commits, útil para trazer as modificações da main, por exemplo

Branch pós-rebase

Controle de Versão com Git

Incorporando Mudanças

git rebase <nome-da-branch>

Exercício (inteiro no terminal, sem usar o GitLab):

  1. Pessoa 1 Crie uma branch do repositório, altere algo e faça commit e push
  2. Pessoa 1 Aguarde a Pessoa 2 fazer o trabalho dela
  3. Pessoa 2 Crie uma branch do repositório, altere algo diferente da Pessoa 1 e faça commit e push
  4. Pessoa 2 Avise a Pessoa 1 que você terminou
  5. Pessoa 1 Incorpore as mudanças da Pessoa 2 executando git fetch e git rebase branch-da-pessoa-2
  6. Pessoa 1 Faça o push da sua branch
  7. Pessoa 1 Pessoa 2 Comparem as diferenças entre incorporar mudanças com merge e rebase

Controle de Versão com Git

Incorporando Mudanças

git merge vs git rebase

Merge: cria um novo commit trazendo as modificações da outra branch

Branch com merge

Rebase: move o início da sua branch para o local especificado

Branch com rebase

GitLab

Funcionalidades

GitLab

Funcionalidades

Vamos ver as funcionalidades de forks que o Github nos oferece

GitHub

Fazendo fork do repositório

Cria uma cópia de um repositório para a sua conta, permitindo trabalhar em projetos que você não possui acesso de escrita

Após o término do desenvolvimento, é possível abrir pull requests do seu repositório para o do projeto "real"

GitHub

Fazendo fork do repositório

git remote

Já vimos como lidar com servidores remotos com esse comando, que também permite buscarmos informações de dois lugares distintos


                            $ git clone https://endereco.do.repositorio.forkado/repositorio
                            $ cd repositorio
                            $ git remote add upstream https://endereco.do.repositorio.original/repositorio
                            $ git pull upstream main
                            From endereco.do.repositorio.original/repositorio
                             * branch            main       -> FETCH_HEAD
                            Updating 4376dc6..4d5f660
                            Fast-forward
                             README.md | 1 +
                             1 file changed, 1 insertion(+)
                             create mode 100644 README.md
                            $ git push origin main
                        

GitHub

Fazendo fork do repositório

Exercício

  1. Pessoa 1 (GitHub) Crie uma issue no seu repositório particular com a atividade "Criar um arquivo de instruções do repositório" e atribua à Pessoa 2
  2. Pessoa 1 (GitHub) Vá em Settings > Collaborators e adicione a Pessoa 2 como Read ou Triage
  3. Pessoa 2 (GitHub) Faça o fork do repositório da Pessoa 1
  4. Pessoa 2 Clone a cópia ("fork") do repositório em sua máquina e adicione um servidor remoto com o nome upstream apontando para o repositório original da Pessoa 1
  5. Pessoa 1 Crie algum outro arquivo (que não o README.md) no seu repositório e faça o push
  6. Pessoa 2 Crie uma branch com o número da issue criada e crie um arquivo README.md com alguma instrução
    • Dica: utilize o stackedit.io para criar o arquivo e copie o código Markdown
  7. Pessoa 2 Atualize o seu repositório buscando os dados da branch main do servidor remoto upstream e confira se o arquivo criado no passo 5. foi copiado
  8. Pessoa 2 (GitHub) Abra um pull request para o repositório original
  9. Pessoa 1 (GitHub) Aprove e faça o merge do pull request da Pessoa 2

Capítulo 8

Controle de Versão com Git: Comandos Avançados

Controle de Versão com Git

Releases

Já vimos anteriormente como criar tags com git tag, mas o GitHub possui uma funcionalidade para facilitar a publicação de versões do seu projeto, permitindo adicionar changelogs, binários e outros arquivos para quem estiver navegando nele.

Releases | GitHub Docs

Controle de Versão com Git

Releases

Exercício

Em seu repositório pessoal, crie uma release 1.0 com um simples texto descrevendo as mudanças daquela versão do seu sistema ("changelog")

Quando formos trabalhar com CI/CD, veremos como automatizar a geração de releases, incluindo arquivos de build
Releases | GitHub Docs

Controle de Versão com Git

Ignorando arquivos

Para ignorar a adição de determinados arquivos (ou pastas inteiras), podemos criar um arquivo chamado .gitignore e especificar os caminhos que desejamos ignorar


                            # Ignora inteiramente as pastas build e dist
                            build/
                            dist/

                            # Ignora todos os arquivos .log nessa pasta
                            *.log

                            # Ignora todos os arquivos .bkp em qualquer pasta
                            **/*.bkp
                        
Essa funcionalidade não se aplica a arquivos que já estão sendo monitorados pelo Git
Git - gitignore Documentation

Controle de Versão com Git

Ignorando arquivos

Dica: confira alguns templates de .gitignore em github.com/github/gitignore e adicione os padrões mais comuns para seu caso de uso através de um arquivo .gitignore global


                            $ git config core.excludesFile ~/global.gitignore
                        
Git - gitignore Documentation

Controle de Versão com Git

Comandos Avançados

git clean

Remove os arquivos não-rastreados da sua área de trabalho


                            $ git status
                            On branch main

                            Untracked files:
                              (use "git add <file>..." to include in what will be committed)
                                arquivo1
                                arquivo2
                                arquivo3
                                arquivo4

                            nothing added to commit but untracked files present (use "git add" to track)

                            $ git clean -n
                            Would remove arquivo1
                            Would remove arquivo2
                            Would remove arquivo3
                            Would remove arquivo4
                        
Dica: use o parâmetro -n (ou --dry-run) para apenas exibir o que seria feito e então o -i para trabalhar de forma interativa

Controle de Versão com Git

Comandos Avançados

git commit --amend

Substitui o último commit por um novo a partir do estado atual do projeto, fazendo uma "emenda"


                            $ git commit -m "Commit antigo sem um certo arquivo"
                            [main 9be2532] Commit antigo sem um certo arquivo
                             1 file changed, 100 insertions(+)
                            ⁣
                            $ git log --oneline
                            9be2532 (HEAD -> main) Commit antigo sem um certo arquivo
                            54d3769 Commit anterior
                            ⁣
                            $ git add novo-arquivo
                            $ git commit --amend -m "Novo commit com o arquivo adicionado"
                            [main 9fa3283] Novo commit com o arquivo adicionado
                             2 files changed, 200 insertions(+)
                             create mode 100644 novo-arquivo
                            ⁣
                            $ git log --oneline
                            9fa3283 (HEAD -> main) Novo commit com o arquivo adicionado
                            54d3769 Commit anterior
                        

Controle de Versão com Git

Comandos Avançados

git commit --amend

Exercício

Faça um commit (sem push) em seu repositório, altere alguma coisa em qualquer arquivo, execute o amend e compare

Controle de Versão com Git

Controle de Dependências

Quase toda linguagem de programação possui um modo para gerenciar de dependências, seja através de bibliotecas externas ou embutido na própria linguagem

Nesses casos, as definições de cada dependência são controlados por arquivos, que devem fazer parte do versionamento para acompanhar o código

Exemplos de arquivos para controle de dependências em algumas linguagens
Linguagem Ferramenta Arquivo
Go Nativo da linguagem go.mod
Java Maven pom.xml
Node npm package.json e package.lock
Node yarn package.json e yarn.lock
PHP Composer composer.json e composer.lock
Python pip requirements.txt

Controle de Versão com Git

Controle de Dependências

git submodule

Comando utilizado para "embutir" outro repositório Git dentro do seu projeto


                            // Para adicionar um projeto externo em seu repositório, execute:
                            $ git submodule add endereco.de.um.repositorio.git pasta/de/destino

                            // Para clonar um repositório e todos seus submódulos (como esta apostila), execute:
                            $ git clone --recursive endereco.de.um.repositorio.git.com.submodulos

                            // Caso não tenha clonado recursivamente, você pode inicializar os submódulos com:
                            $ git submodule update --init --recursive
                        
Git - Submodules

Controle de Versão com Git

Controle de Dependências

git submodule

Exercício

No repositório pessoal de vocês, incluam o repositório de exercícios como submódulo em uma pasta chamada sub-exercicio

Capítulo 9

Controle de Versão com Git: Comandos Avançados (cont.)

Controle de Versão com Git

Comandos Avançados

git stash

Salva as diferenças atuais do projeto (que ainda não estão em um commit) em uma área à parte, possibilitando rapidamente recuperá-las posteriormente


                            $ git status
                            On branch main
                            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:   arquivo

                            no changes added to commit (use "git add" and/or "git commit -a")
                            $ git stash push
                            Saved working directory and index state WIP on main: a1d4cfc Criando arquivo
                            $ git status
                            On branch main
                            nothing to commit, working tree clean
                            $ git stash pop
                            On branch main
                            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:   arquivo

                            no changes added to commit (use "git add" and/or "git commit -a")
                            Dropped refs/stash@{0} (66650bc83e829d949d6ba24833962f539de87aa9)
                        
Git - git-stash Documentation

Controle de Versão com Git

Comandos Avançados

git reflog


                            $ echo "Conteúdo antigo do arquivo" > arquivo
                            $ git add arquivo
                            $ git commit -m "Criando arquivo"
                            [main (root-commit) ed2ad40] Criando arquivo
                             1 file changed, 1 insertion(+)
                             create mode 100644 arquivo
                            ⁣
                            $ echo "Melhorei o arquivo" > arquivo
                            $ git commit -am "Melhorei o arquivo"
                            [main d160187] Melhorei o arquivo
                             1 file changed, 1 insertion(+), 1 deletion(-)
                            $ git log --oneline
                            d160187 (HEAD -> main) Melhorei o arquivo
                            ed2ad40 Criando arquivo
                            $ git reflog
                            d160187 (HEAD -> main) HEAD@{0}: commit: Melhorei o arquivo
                            ed2ad40 HEAD@{1}: commit (initial): Criando arquivo
                            ⁣
                            $ git reset --hard HEAD~1
                            HEAD is now at ed2ad40 Criando arquivo
                            $ cat arquivo
                            Conteúdo antigo do arquivo
                            $ git log
                            ed2ad40 (HEAD -> main) Criando arquivo
                            ⁣
                            $ git reflog
                            ed2ad40 (HEAD -> main) HEAD@{0}: reset: moving to ed2ad40835f5f06e7e61317d2aa2e6c898332ffc
                            d160187 HEAD@{1}: commit: Melhorei o arquivo
                            ed2ad40 (HEAD -> main) HEAD@{2}: commit (initial): Criando arquivo
                            ⁣
                            $ git reset HEAD@{1}
                            Unstaged changes after reset:
                            M	arquivo
                            $ git restore arquivo
                            $ cat arquivo
                            Melhorei o arquivo
                        
Git - git-reflog Documentation

Controle de Versão com Git

Comandos Avançados

git rebase -i <referência-do-commit>

Utilizamos o comando "original" sem o argumento -i git rebase <outra-branch> para levar todos os commits da branch atual para outra-branch, como se estivéssemos criado aquela branch a partir dessa outra-branch

Também podemos utilizar este comando com o modo interativo através do argumento -i, permitindo que possamos escolher o que fazer com cada um dos commits

Usar rebase do Git na linha de comando - GitHub Docs

Controle de Versão com Git

Comandos Avançados

git rebase -i <referência-do-commit>

Isso torna esse comando uma das funções mais complexas do Git, pois a utilizamos para reescrever o histórico de uma branch, podendo alterá-lo, mesclar com outros ou até mesmo descartá-lo

Cuidado: os hashes sha-1 dos commits serão reescritos. Por isso, não é muito recomendado usá-lo caso outras pessoas da equipe já tenham baixado as atualizações em suas máquinas, pois podem perder código!
Usar rebase do Git na linha de comando - GitHub Docs

Controle de Versão com Git

Comandos Avançados

git rebase -i <referência-do-commit>

Para reescrever os últimos 5 commits, basta executarmos:


                            $ git rebase -i HEAD~5
                        

Então, um editor de texto irá abrir com a lista desses 5 commits, prefixados pelo comando pick (que significa que queremos usar esse commit exatamente como ele está):


                            pick 8cdd9b63 Mensagem do commit
                            pick 529f9db2 Mensagem do commit
                            pick 99769a26 Mensagem do commit
                            pick d81cefdf Mensagem do commit
                            pick a3a39d99 Mensagem do commit
                            pick a85a9d96 Mensagem do commit
                        
Usar rebase do Git na linha de comando - GitHub Docs

Controle de Versão com Git

Comandos Avançados

git rebase -i <referência-do-commit>

Para alterar um commit específico, basta renomearmos pick para os comandos permitidos (alguns listados abaixo) e salvar o arquivo

Atalho Comando Descrição
p pick usa o commit como está (padrão)
r reword usa o commit mas edita a mensagem
e edit usa o commit, mas para o processo para você poder fazer qualquer alteração no projeto
s squash usa o commit mas incorpora no commit anterior, gerando um só
f fixup como squash, mas descarta a mensagem desse commit
d drop descarta o commit
Usar rebase do Git na linha de comando - GitHub Docs

Controle de Versão com Git

Comandos Avançados

git push -f

Se reescrevemos o histórico com git rebase -i, um simples git push não será o suficiente para subirmos as modificações, já que os commits em nossa máquina local estão muito diferentes do que estão no servidor remoto


                            $ git push
                            To endereco.do.servidor.com:repositorio.git
                             ! [rejected]        main -> main (non-fast-forward)
                            error: failed to push some refs to 'endereco.do.servidor.com:repositorio.git'
                            hint: Updates were rejected because the tip of your current branch is behind
                            hint: its remote counterpart. Integrate the remote changes (e.g.
                            hint: 'git pull ...') before pushing again.
                            hint: See the 'Note about fast-forwards' in 'git push --help' for details.
                        

Controle de Versão com Git

Comandos Avançados

git push -f

Então, temos que utilizar o parâmetro -f para forçar o envio das atualizações


                            $ git push -f
                        

Controle de Versão com Git

Comandos Avançados

Exercício

No repositório de exercícios, crie uma branch com seu nome e utilize o git rebase -i para alterar os últimos 6 commits do repositório

  • Junte os commits 56d56e6 e 89165dd em um só e com apenas uma mensagem
  • Descarte o commit 12f556c
  • Altere a mensagem do commit a5733eb para "Movendo arquivos anteriores para uma pasta chamada antigos"
  • Faça o push e abra uma merge request, me colocando como revisor
Lembre-se de sempre executar o git pull antes de criar sua branch para mantê-la atualizada (ou use git rebase após)

Capítulo 10

Relembrando conceitos

Relembrando conceitos

Revimos os principais comandos do Git

Capítulo 11

Mais Comandos e CI/CD

Controle de Versão com Git

Comandos Avançados

git grep

Busca por um texto nos arquivos da área de trabalho (ou em outros branches)


                            $ git grep "stash"
                            docs/index.html: <h3><code>git stash</code></h3>
                            docs/index.html:     $ git stash push
                            docs/index.html:     $ git stash pop
                            docs/index.html:     Dropped refs/stash@{0} (66650bc83e829d949d6ba24833962f539de87aa9)
                            docs/index.html: <a href="https://git-scm.com/docs/git-stash/pt_BR" target="_blank" rel="noopener"
                            docs/index.html:    class="reference">Git - git-stash Documentation</a>
                        
Git - git-grep Documentation

Controle de Versão com Git

Comandos Avançados

git grep

Busca por um texto nos arquivos da área de trabalho (ou em outros branches)

O parâmetro -n mostra o número da linha:


                            $ git grep -n "stash"
                            docs/index.html:2331: <h3><code>git stash</code></h3>
                            docs/index.html:2345:     $ git stash push
                            docs/index.html:2350:     $ git stash pop
                            docs/index.html:2358:     Dropped refs/stash@{0} (66650bc83e829d949d6ba24833962f539de87aa9)
                            docs/index.html:2360: <a href="https://git-scm.com/docs/git-stash/pt_BR" target="_blank" rel="noopener"
                            docs/index.html:2361:    class="reference">Git - git-stash Documentation</a>
                        
Git - git-grep Documentation

Controle de Versão com Git

Comandos Avançados

git grep

Busca por um texto nos arquivos da área de trabalho (ou em outros branches)

O parâmetro -c mostra um sumário com a contagem de linhas com ocorrências por arquivo:


                            $ git grep -c "stash"
                            docs/index.html:20
                        
Git - git-grep Documentation

Controle de Versão com Git

Comandos Avançados

git remote prune ou git fetch -p

Apagam referências a branches que não existem mais no servidor remoto


                            $ git fetch -p
                            From gitlab.com:repositorio
                             - [deleted]         (none)     -> origin/feature/nova-tela-de-login
                             - [deleted]         (none)     -> origin/fix/cookie-incorreto
                        

Controle de Versão com Git

Comandos Avançados

git bisect

Encontra o commit em que um bug foi introduzido no projeto

  1. Comece executando git bisect start para iniciar a investigação

                            $ git bisect start
                            status: waiting for both good and bad commits

                            $ git status
                            On branch main
                            Your branch is up to date with 'origin/main'.

                            You are currently bisecting, started from branch 'main'.
                              (use "git bisect reset" to get back to the original branch)

                            nothing to commit, working tree clean
                        
Documentação oficial: git bisect

Controle de Versão com Git

Comandos Avançados

git bisect

Encontra o commit em que um bug foi introduzido no projeto

  1. Teste sua aplicação e marque o commit atual como bom ou ruim com git bisect good ou git bisect bad

                            $ git bisect bad
                            status: waiting for good commit(s), bad commit known
                        
Documentação oficial: git bisect

Controle de Versão com Git

Comandos Avançados

git bisect

Encontra o commit em que um bug foi introduzido no projeto

  1. Encontre algum commit anterior que você saiba que estava funcionando e marque-o com git bisect good

                            $ git bisect good 4229cee31dac9c0a6d6ea6e420861c01eaede4a4
                            Bisecting: 0 revisions left to test after this (roughly 1 step)
                            [0f80cdc281324cd118e9f3c065096627d1258d6b] Alguma alteração

                            $ git status
                            HEAD detached at 0f80cdc
                            You are currently bisecting, started from branch 'main'.
                              (use "git bisect reset" to get back to the original branch)

                            nothing to commit, working tree clean
                        
Documentação oficial: git bisect

Controle de Versão com Git

Comandos Avançados

git bisect

Encontra o commit em que um bug foi introduzido no projeto

  1. Execute o mesmo procedimento de marcar com git bisect good ou git bisect bad

                            $ git bisect bad
                            Bisecting: 0 revisions left to test after this (roughly 0 steps)
                            [66facecc2ec5eedf8f3f248318b4b61e16d0a54c] Outra alteração

                            $ git status
                            HEAD detached at 66facec
                            You are currently bisecting, started from branch 'main'.
                              (use "git bisect reset" to get back to the original branch)

                            nothing to commit, working tree clean
                        
Documentação oficial: git bisect

Controle de Versão com Git

Comandos Avançados

git bisect

Encontra o commit em que um bug foi introduzido no projeto

  1. Você eventualmente vai chegar até o commit que introduziu o bug

                            $ git bisect good
                            552da6fa8f6fad69197b56a8666a8262b692f403 is the first bad commit
                            commit 552da6fa8f6fad69197b56a8666a8262b692f403
                            Author: ...
                            Date:   ...

                            Mensagem do commit

                            arquivo | 10 +++++
                            1 file changed, 10 insertions(+)
                        
Documentação oficial: git bisect

Controle de Versão com Git

Comandos Avançados

git bisect

Exercício

No repositório de exercícios, encontre qual commit introduziu um bug que permite cadastrar produtos sem preço

  1. Atualize seu repositório de exercícios
  2. Execute o script run que está na pasta bisect
    
                                        $ cd bisect
                                        $ ./run
                                        Uso:
                                          ./run -n "Nome do produto" -d "Descrição do produto" -p Preço
    
                                        Opções:
                                          -n <nome do produto>  Fornece o nome do produto
                                          -d <descrição>        Forneça a descrição do produto
                                          -p <preço do produto> Fornece o preço do produto
                                    

Controle de Versão com Git

Comandos Avançados

git bisect

Exercício

Encontre qual commit introduziu um bug que permite cadastrar produtos sem preço

  1. Passe os argumentos de nome e descrição para o script mas não o de preço e veja que ele reclama o erro mas permite cadastrar mesmo assim
    
                                        $ ./run -n "Meu produto" -d "Descrição do produto"
                                        Erro: você deve informar um preço
                                        Criando produto...
                                         [🛈] Nome:      Meu produto
                                         [🛈] Descrição: Descrição do produto
                                         [🛈] Preço:     R$ 0,00
    
                                        Produto criado com sucesso!
                                    
  2. Use o git bisect para descobrir qual commit criou o bug, executando o comando acima e vendo quando estava funcionando (ou seja, se não passar o preço, não cria o produto)

CI/CD

CI/CD

Conceitos

CI/CD, continuous integration/continuous delivery, é um método para entregar aplicações com frequência aos clientes. Para isso, é aplicada a automação nas etapas do desenvolvimento de aplicações. Os principais conceitos atribuídos a esse método são a integração, entrega e implantação contínuas.
O que é CI/CD? (Red Hat)

CI/CD

Conceitos

Especificamente, o CI/CD aplica monitoramento e automação contínuos em todo o ciclo de vida das aplicações, incluindo as etapas de teste e integração, além da entrega e implantação. Juntas, essas práticas relacionadas são muitas vezes chamadas de "pipeline de CI/CD" e são compatíveis com o trabalho conjunto das equipes de operações e desenvolvimento com métodos ágeis.
O que é CI/CD? (Red Hat)

CI/CD

Conceitos

O acrônimo CI/CD tem alguns significados. "CI" sempre se refere à integração contínua, que é um processo de automação para desenvolvedores. "CD" se refere à entrega contínua e/ou à implantação contínua, conceitos relacionados e usados alternadamente às vezes.
CI/CD O que é CI/CD? (Red Hat)

CI/CD

Ferramentas de CI

CI/CD

Exemplos

  • Executar o comando sqlfluff sempre que uma merge request for aberta para garantir que os scripts SQL estão formatados de acordo com o padrão desejado
  • Executar o comando python -m unittest sempre que uma merge request for aberta para rodar os testes da sua aplicação e verificar se o que foi feito não irá quebrar nada
  • Executar o comando mvn compile para compilar sua aplicação Java em um arquivo executável
  • Subir os arquivos compilados (chamados de "artefatos") no Package Registry do GitLab
  • Criar uma nova release e adicionar os artefatos gerados
Get started with GitHub Actions | GitHub Docs

Capítulo 12

CI/CD (cont.)

CI/CD

GitHub Actions

Conceitos

Jobs
Cada ação que será executada, por exemplo os comandos para testar sua aplicação ou fazer deploy em algum servidor
Steps
Passos dentro de um job, como rodar um comando ou usar uma action pronta
Workflows
Conjunto de jobs e steps definidos em um arquivo YAML, que são executados em resposta a eventos (push, pull request, etc)
Runners
Ambiente onde os jobs são executados (por exemplo, máquinas virtuais hospedadas pelo GitHub)

CI/CD

GitHub Actions

É configurado a partir de arquivos YAML na pasta .github/workflows/ do seu repositório, onde você define tudo que deseja executar de acordo com alguns gatilhos (eventos)

Workflow syntax for GitHub Actions

CI/CD

GitHub Actions

Você pode configurar para que o merge só seja permitido se todos os jobs do workflow passarem, em SettingsBranchesBranch protection rulesRequire status checks to pass before merging

About protected branches | GitHub Docs

CI/CD

GitHub Actions

Exemplo:


                            name: Java CI

                            on:
                              push:
                                branches: [ main ]
                              pull_request:
                                branches: [ main ]

                            jobs:
                              build:
                                runs-on: ubuntu-latest
                                steps:
                                  - uses: actions/checkout@v3
                                  - name: Set up JDK 8
                                    uses: actions/setup-java@v3
                                    with:
                                      java-version: '8'
                                      distribution: 'adopt'
                                  - name: Build with Maven
                                    run: ./mvnw package

                              deploy:
                                needs: build
                                runs-on: ubuntu-latest
                                if: github.ref == 'refs/heads/main'
                                steps:
                                  - uses: actions/checkout@v3
                                  - name: Deploy
                                    run: echo "Deploy step aqui"
                        
Building and testing Java with Maven | GitHub Docs

CI/CD

GitHub Actions

Exercício 1:

  • Em uma nova branch em seu repositório pessoal, crie um arquivo .github/workflows/ci.yml
  • Crie um job para rodar o comando abaixo:
    
                                        sqlfluff lint --dialect oracle
                                    
  • Crie um arquivo .sql com algum código
  • Abra um pull request e acompanhe o resultado do CI, arrumando os arquivos até que passe
  • Faça o merge para a branch principal
Não se esqueça de atualizar seu repositório antes de criar a branch e veja como rodar jobs apenas em pull requests usando o evento pull_request

Capítulo 13

CI/CD (cont.)

CI/CD

GitHub Actions

Exercício 2: Adapte seu workflow para adicionar jobs de deploy apenas em eventos de tag...

  1. Gere um artefato a partir de todos os arquivos .sql, usando como nome a tag
  2. Crie uma release usando o nome da tag
  3. Adicione o artefato do passo 1 como um asset na release

Então, crie uma tag (com qualquer versão) em seu código e acompanhe o resultado

Dicas

CI/CD

GitHub Actions

Exercício de deploy

  1. Em seu repositório pessoal, crie secrets para armazenar variáveis sensíveis, como usuário e senha de banco de dados
  2. No workflow, use os secrets para acessar essas variáveis em jobs de deploy

CI/CD

GitHub Actions

Exercício de deploy

  1. Crie um job que irá executar o comando abaixo somente em push para a branch develop:
    
                                        $ sqlplus "${{ secrets.ORACLE_USER_STAGING }}/${{ secrets.ORACLE_PASSWORD_STAGING }}@${{ secrets.ORACLE_CONNECTION_STRING }}" < <(cat *.sql)
                                    

    Dica: esse comando irá concatenar todos os arquivos .sql em um só e passá-lo para o sqlplus

  2. Crie um job que irá executar o comando abaixo somente em push para a branch main:
    
                                        $ sqlplus "${{ secrets.ORACLE_USER_PRODUCTION }}/${{ secrets.ORACLE_PASSWORD_PRODUCTION }}@${{ secrets.ORACLE_CONNECTION_STRING }}" < <(cat *.sql)
                                    
PS: a variável ORACLE_CONNECTION_STRING pode ser definida como secret global ou variável de ambiente
Environment variables | GitHub Docs

CI/CD

GitHub Actions

Exercício de deploy

  1. Crie a branch develop e faça commits diretamente nela, acompanhando a execução do workflow
  2. Faça commits diretamente na branch main e acompanhe a execução do workflow

Capítulo 14

Hooks
Boas e más práticas

Hooks

Hooks

Scripts que são executados automaticamente de acordo com alguns eventos que acontecem em seu repositório local

Para criar um hook, acesse a pasta .git/hooks de seu repositório e crie um arquivo executável com o nome dos eventos (removendo o sufixo .sample)


                            $ cd .git/hooks
                            $ ls
                            applypatch-msg.sample      pre-commit.sample          pre-receive.sample
                            commit-msg.sample          pre-merge-commit.sample    push-to-checkout.sample
                            fsmonitor-watchman.sample  prepare-commit-msg.sample  update.sample
                            post-update.sample         pre-push.sample
                            pre-applypatch.sample      pre-rebase.sample

                            $ touch pre-commit
                            $ chmod +x .git/hooks/pre-commit
                        
Hooks não fazem parte do repositório central, sendo específicos do seu computador apenas!
Git - Git Hooks githooks.com

Boas e más práticas

Boas práticas

Use SSH

Ao invés de utilizar HTTPS para se comunicar com o servidor de origem, podemos usar SSH.

Exercício:

Boas e más práticas

  • Não faça commits direto nas branches principais (main, master, production, etc). Crie sua própria branch e faça pull requests!
  • Mantenha branches limpas e resolvendo uma única issue, com bons nomes;
  • Faça commits atômicos: isto é, que englobem uma única mudança (uma funcionalidade criada ou um bug corrigido);
  • Faça commits frequentes para não perder dados caso aconteça algo (ou para que outra pessoa possa dar continuidade no seu trabalho);
    • Essas duas práticas acima facilitam bastante o uso do git bisect, por exemplo
  • Configure o arquivo .gitignore para evitar subir arquivos de configuração, valores sensíveis ou outras informações que são relativas a ambientes e não ao desenvolvimento;

Boas e más práticas

  • Ao fazer code review de merge requests, seja educado(a)!
    Dica: utilize Conventional Commits
  • Ao fazer um commit, explique de forma sucinta (mas significativa) o que você está fazendo;
    Dica: utilize Conventional Comments
  • Se possível, divida arquivos grandes em menores para facilitar as operações do Git;
  • Bloqueie o uso do git push -f para não-mantenedores do repositório e, mesmo assim, não exagere no uso;

Boas e más práticas

Algumas referências de leitura:

Referências

Referências