Capítulo 1
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)
Principais benefícios:
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
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
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
Alguns dos principais Sistemas de Controle de Versão são:
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?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)
Capítulo 2
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:
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
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...
minha-aplicacao
build
diff
e patch
do Unix,
sem precisar de sistemas de controle de versão!
$ diff -ruN minha-aplicacao/ > mudancas.path
$ patch -p0 < mudancas.patch
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
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
)
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
Área em que arquivos são adicionados para indicar que estão preparados para serem incluídos no commit
Instruções de instalação do git para cada Sistema Operacional:
git init
Inicializa o diretório atual para ser utilizado como repositório, criando a pasta
.git
git remote
Gerencia os endereços dos servidores remotos para atualização e sincronização do repositório
Documentação oficial: git remotegit 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 cloneNo Github (e em outras plataformas), pode ser feito através dos protocolos HTTP e SSH
Clonando um repositório | GitHub Docsgit 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
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
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
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
git log
Mostra o histórico de commits naquele branch ou de um arquivo específico
Documentação oficial: git loggit push
Envia os commits que estão no repositório local para o servidor remoto
Documentação oficial: git pushCapítulo 3
git mv
Move ou renomeia um arquivo da cópia de trabalho
Documentação oficial: git mvgit rm
Remove um arquivo da cópia de trabalho
Documentação oficial: git rmgit diff
Mostra as diferenças entre os arquivos atuais e o que está no servidor remoto ou entre commits
Documentação oficial: git diffgit show
Exibe detalhes de um commit, tag ou de um arquivo específico
Documentação oficial: git showgit fetch
Atualiza os metadados do repositório a partir do servidor remoto
Documentação oficial: git fetchgit 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)
git --help
Todos os comandos do git possuem um parâmetro --help
para mostrar mais detalhes
sobre como podemos usá-los!
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 loggit 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
git log
Para ter uma visão mais compacta, podemos usar o parâmetro --oneline
:
$ git log --oneline
Documentação oficial: git log
git log
Para saber os arquivos modificados, utilize --stat
:
$ git log --stat
Documentação oficial: git log
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
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
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
git log
Para buscar apenas os commits que possuem certa mensagem, utilize
--grep
:
$ git log --grep "Parte da mensagem"
Documentação oficial: git log
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
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
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
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
git shortlog
Forma de visualizar o histórico do git log
de uma forma mais simples
git blame
Saiba qual foi a última modificação em cada linha do arquivo
Documentação oficial: git blameCapítulo 4
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 checkoutgit branch
Lista, cria ou exclui branches, podendo também mostrar as que contém ou não determinado commit
Documentação oficial: git branchgit 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
git branch
Para excluir um branch do servidor remoto:
$ git push -d origin nome-do-branch
Documentação oficial: git branch
Vamos ver algumas configurações possíveis para gerenciamento dos projetos no GitHub:
README
;Capítulo 5
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:
main
)
main
) possui códigos que estão prontos para
serem publicados em produção ou disponibilizados para os clientes
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
main
e develop
develop
, que será mesclada de volta ao fim do
desenvolvimento
release
será criada a partir
da develop
develop
não deve conter novos
recursos, apenas correções de segurança, melhorias de implementação ou documentação
release
para a
main
Exemplo:
main
, temos a versão atual
develop
a partir da v1.0
develop
develop
release
release
para a main
e geramos uma nova versão para
publicar
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)
O merge é utilizado quando queremos incorporar todas as modificações efetuadas em uma branch em uma outra
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
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
$ 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
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:
<<<<<<<
e vai até
=======
, mostra o que temos atualmente no HEAD
=======
até o próximo
>>>>>>>
) nos informa o que está vindo da
develop
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
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
Pode se tornar difícil resolver esses conflitos manualmente, então dê preferência a resolvê-los com algumas ferramentas:
Capítulo 6
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
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
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
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")
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
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
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
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
git merge <nome-da-branch>
Exercício
Pessoa 1
git fetch
e git merge branch-da-pessoa-2
Pessoa 2
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
git cherry-pick <referência>
Exercício
Pessoa 1
git fetch
e git cherry-pick <hash-do-commit>
Pessoa 2
Capítulo 7
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
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
git rebase <nome-da-branch>
Exercício (inteiro no terminal, sem usar o GitLab):
git fetch
e git rebase branch-da-pessoa-2
git merge
vs git rebase
Merge: cria um novo commit trazendo as modificações da outra branch
Rebase: move o início da sua branch para o local especificado
Vamos ver as funcionalidades de forks que o Github nos oferece
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"
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
Exercício
Read
ou Triage
upstream
apontando para o repositório
original da Pessoa 1
README.md
) no seu
repositório e faça o push
README.md
com alguma instrução
main
do
servidor remoto upstream
e confira se o arquivo criado no passo
5. foi copiado
Capítulo 8
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.
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")
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
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
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
-n
(ou --dry-run
) para apenas exibir o que
seria feito e então o -i
para trabalhar de forma interativa
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
git commit --amend
Faça um commit (sem push) em seu repositório, altere alguma coisa em qualquer arquivo, execute o amend e compare
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
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 |
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
git submodule
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
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
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
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
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
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
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 |
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.
git push -f
Então, temos que utilizar o parâmetro -f
para forçar o envio das atualizações
$ git push -f
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
56d56e6
e 89165dd
em um só e com
apenas uma mensagem
12f556c
a5733eb
para
"Movendo arquivos anteriores para uma pasta chamada antigos"
git pull
antes de criar sua
branch para mantê-la atualizada (ou use git rebase
após)
Capítulo 10
Revimos os principais comandos do Git
Capítulo 11
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
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
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
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
git bisect
Encontra o commit em que um bug foi introduzido no projeto
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
git bisect
Encontra o commit em que um bug foi introduzido no projeto
git bisect good
ou git bisect bad
$ git bisect bad
status: waiting for good commit(s), bad commit known
Documentação oficial: git bisect
git bisect
Encontra o commit em que um bug foi introduzido no projeto
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
git bisect
Encontra o commit em que um bug foi introduzido no projeto
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
git bisect
Encontra o commit em que um bug foi introduzido no projeto
$ 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
git bisect
No repositório de exercícios, encontre qual commit introduziu um bug que permite cadastrar produtos sem preço
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
git bisect
Encontre qual commit introduziu um bug que permite cadastrar produtos sem preço
$ ./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!
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, 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)
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)
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.
sqlfluff
sempre que uma merge request for
aberta para garantir que os scripts SQL estão formatados de acordo com o padrão
desejado
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
mvn compile
para compilar sua aplicação Java em um
arquivo executável
Capítulo 12
É 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)
Você pode configurar para que o merge só seja permitido se todos os jobs do workflow passarem, em Settings → Branches → Branch protection rules → Require status checks to pass before merging
About protected branches | GitHub DocsExemplo:
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
Exercício 1:
.github/workflows/ci.yml
sqlfluff lint --dialect oracle
.sql
com algum código
pull_request
Capítulo 13
Exercício 2: Adapte seu workflow para adicionar jobs de deploy apenas em eventos de tag...
.sql
, usando como nome a tag
Então, crie uma tag (com qualquer versão) em seu código e acompanhe o resultado
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
main
:
$ sqlplus "${{ secrets.ORACLE_USER_PRODUCTION }}/${{ secrets.ORACLE_PASSWORD_PRODUCTION }}@${{ secrets.ORACLE_CONNECTION_STRING }}" < <(cat *.sql)
ORACLE_CONNECTION_STRING
pode ser definida como secret global ou variável de ambiente
develop
e faça commits diretamente nela,
acompanhando a execução do workflow
main
e acompanhe a
execução do workflow
Capítulo 14
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
Ao invés de utilizar HTTPS para se comunicar com o servidor de origem, podemos usar SSH.
Exercício:
git pull
main
,
master
, production
, etc). Crie sua própria branch e
faça pull requests!
git bisect
,
por exemplo
.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;
git push -f
para não-mantenedores do repositório e,
mesmo assim, não exagere no uso;
Algumas referências de leitura: