Skip to main content

Learning GIT



Introdução


O GIT é um sistema para controle de versão criado por Linus Tovalds (que também criou o kernel do Linux), com ele podemos manter o histórico do código e manter uma rastreabilidade de tudo que foi alterado nele, com isso podemos desfazer qualquer alteração que tenha sido feita. Não só isso, ele possui outras funcionalidade incríveis como o sistema de branch, vou deixar essas terminologias para serem explicadas quando chegarem sua hora.



Instalação


Para fazer a instalação no Linux, em distros baseadas em Debian, use o comando abaixo:

# Instalando o git:
$› sudo apt install git -y


Configurando


A configuração do Git é bem básica e simples. Vamos ver como realizar configurações.

# Configurando o Usuário:
$› git config --global user.name "SEU_USUARIO"

# Configurando o Email:
$› git config --global user.email "SEU_EMAIL"

# Configurando o editor de preferencia:
$› git config --global core.editor vim

Essas configurações vão ser salvas em: ~/.gitconfig (padrão) ou ~/.config/git/.gitconfig.


Segue um exemplo do arquivo:

$› cat ~/.gitconfig 
[user]
email = SEU_EMAIL
name = SEU_USUARIO
[core]
editor = vim


Clonando um repositório


Uma das grandes ferramentas do Git é poder clonar um repositório, isso é o mesmo que fazer uma cópia completa de um repositório que está num servidor remoto e colar no seu computador, para clonar um repo (repositório) usamos a opção clone do comando git.

# Clonando meu repositório via HTTPS:
$› git clone https://github.com/FULANO/gittest
Cloning into 'sysadmin'...
remote: Enumerating objects: 128, done.
remote: Counting objects: 100% (128/128), done.
remote: Compressing objects: 100% (105/105), done.
remote: Total 128 (delta 54), reused 81 (delta 21), pack-reused 0
Receiving objects: 100% (128/128), 935.95 KiB | 5.85 MiB/s, done.
Resolving deltas: 100% (54/54), done.

# Uma outra forma de clonar um repositório é usando SSH, para isso você deve adicionar uma chave ao Github:
$› git clone git@github.com:FULANO/gittest.git
Cloning into 'sysadmin'...
Enter passphrase for key '/home/FULANO/.ssh/git':
remote: Enumerating objects: 128, done.
remote: Counting objects: 100% (128/128), done.
remote: Compressing objects: 100% (105/105), done.
remote: Total 128 (delta 54), reused 81 (delta 21), pack-reused 0
Receiving objects: 100% (128/128), 935.95 KiB | 1.54 MiB/s, done.
Resolving deltas: 100% (54/54), done.


Criando e clonando um repositório


Acima vimos como usar o Git com repositórios remotos sendo eles o GitHub ou GitLab, mas é possível termos um repositório remoto no nosso servidor.

# Criar um repositório remoto no servidor:
$ sudo mkdir /opt/git_repos/

# Entre na pasta:
$ cd /opt/git_repos/

# Inicie o repositório em modo remoto:
$ sudo git init --bare myrepo.git
Initialized empty Git repository in /opt/git_repos/myrepo.git/

O parâmetro --bare serve para que o Git não crie um working tree, impedindo que commits sejam efetuados diretamente no nesse diretório.


Agora em outra pasta clone esse repositório:

$ git clone file:///opt/git_repos/myrepo.git
Cloning into 'myrepo'...
warning: You appear to have cloned an empty repository.

# A mensagem é normal já que não temos nada no repositório remoto ainda.

# Como nosso primeiro commita faça:
$ touch .gitkeep
$ git add .gitkeep
$ git commit -m "add .gitkeep"
[master (root-commit) 83375cc] add .gitkeep
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 .gitkeep

$ git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 213 bytes | 106.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To file:///opt/git_repos/myrepo.git
* [new branch] master -> master



# Agora de outro diretório clone novamente:
$ git clone file:///opt/git_repos/myrepo.git
Cloning into 'myrepo'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (3/3), done.

## Sem mensagem de alerta!

Deixei o diretório do repositório com permissão 777 apenas para facilitar, num ambiente de produção deve ser aplicar permissão por grupos, similar ao que fiz com o gopass.


Agora para compartilhar isso na Rede podemos criar contas de usuários com acesso SSH, então cada usuário teria que acessar diretamente o servidor para ter acesso ao git. Esse seria o modo mais fácil, para ver a documentação completa veja aqui.



Processo de envio para o repo remoto


Vamos ver qual o processo que ocorre até que um arquivo seja enviado para o servidor remoto do Git.


Working Dir

Também conhecido como working tree, essa é a etapa onde o arquivo está apenas na nossa máquina, o Git não conhece ele, não existe snapshot desse arquivo no Git, os arquivos em Working Dir são todos Untracked.


Index

Essa é a etapa onde os arquivos são reunidos para que possa se criar um pacote na próxima etapa. Para fazer com que o arquivo chegue nesse etapa, usamos o comando git add..., sendo assim, para chegar aqui ele só pode ser modified e untracked.


É onde o arquivo fica antes de enviado para o servidor remoto, o pacote com todas as edições já foi fechado, nele contém todas as modificações, logs, hash dos logs, dados de quem modificou e muito mais. Para fazer um arquivo chegar nessa etapa, usamos o comando git commit....



Status


A opção status do Git é usado para vermos o status do repositório/arquivos. Existem alguns detalhes que você deve saber antes de executarmos o comando. O git possui 4 tipos de tags para os arquivos, com isso podemos saber em qual etapa cada arquivo se encontra, isso está diretamente ligado as etapas explicadas acima.


Untracked


Recebem essa tag os arquivos que ainda não são conhecidos pelo GIT, ou seja, que não foram para o repositório remoto nenhuma vez (o git chama isso de snapshot, no caso arquivos que ainda não tiveram seu snapshot), aqui temos arquivos os novos.


Tracked


Esses são arquivos que já foram para o repositório remoto e o GIT conhece eles (tiveram seu snapshot no git). Essa não é uma tag em sí, mas qualquer arquivo que não seja untracked será tracked, mas em alguma de suas sub-catergorias, temos 3 sub-categorias, que são: Unmodified, Modified e Staged.

TagsDescrição
UnmodifiedArquivos que não tiveram nenhuma alteração, do jeito que foram baixados eles estão, idênticos ao seu snapshot no repo remoto.
ModifiedArquivos que foram modificados, seu estado atual é diferente de seu snapshot no repo remoto (o git sabe disso por causa do Index). Um arquivo recebe essa tag quando ele é editado. Após isso ele é enviado para Staged.
StagedO arquivo fica com essa tag quando ele é adicionado ao Index do Git, isso quer dizer que esse arquivo ainda pode ser modificado sem que seja gerado um novo log para essa modificação. Um arquivo fica com essa tag quando ele é untracked e você roda git add... ou quando ele é modified.
Dessa forma, quando você fizer o git commit, todo arquivo como staged será reservado num pacote, esse pacote que será enviado para o servidor remoto, dai as tags serão unmodified novamente.

Dessa forma, quando você fizer o git commit, todo arquivo como staged será reservado num pacote, esse pacote que será enviado para o servidor remoto, dai as tags serão unmodified novamente.


A imagem abaixo é como funciona, ela se encontra no site oficial do Github.

The lifecycle of the status of your files

Vamos ver na prática:

# Rodando o 'git status' no clone que fizemos:
‹chireadan› ‹~/git/gittest› ‹main› $› git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean


# Adicione algum arquivo (arquivo novo):
‹chireadan› ‹~/git/gittest› ‹main› $› touch arquivo1

# Agora veja o status de novo:
$› git status
On branch main
Your branch is up to date with 'origin/main'.

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

nothing added to commit but untracked files present (use "git add" to track)
# Perceba que o arquivo agora está abaixo de 'Untracked files'!

# Adicione esse arquivo a 'staged' (adicionar para dar o commit mesmo):
$› git add arquivo1

# E status de novo:
$› git status
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: arquivo1
# Perceba que ele diz 'use 'git restore --staged <file>...' to unstage', isso significa que ele está como 'staged'!

# Faça o commit:
$› git commit -m "Primeiro arquivo do tutorial Git"
[main 0909346] Primeiro arquivo do tutorial Git
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 arquivo1

# E por fim, faça o push para enviar o arquivo:
$› git push origin main
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 6 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 295 bytes | 295.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:FULANO/gittest.git
1d19a80..0909346 main -> main
# Calma que 'origin' e 'main' serão explicados mais adiante!

Agora o arquivo já foi enviado para o servidor remoto.



Criando um repositório apenas via CLI


Resolvi explicar como criar um repo via cli agora para que possa explicar outras coisas logo em seguida. Antes de prosseguir, você deve configurar o Git como foi explicado mais acima.

# Crie uma pasta que será nosso novo repositório:
$› mkdir gitcli

# Entre nele:
$› cd gitcli

# Inicie o git nesse novo repo:
$› git init
Initialized empty Git repository in /tmp/gitcli/.git/


O que é Origin?


No Git quando vamos fazer o push de algum conteúdo, nós geralmente usamos a sintaxe git push origin main (antigamente era master, hoje em dia é main). Acontece que origin é um apelido para o repositorio que queremos fazer o push, e main é a branch que vamos usar (explicação sobre branch mais para frente).


Se nós não usássemos origin, teriamos que passar todo o caminho do repo, exemplo:

## O caminho para o repo gittest que usamos mais acima seria esse (git@github.com:FULANO/gittest.git),
## Para conexões via ssh.
$› git remote -v
origin git@github.com:FULANO/gittest.git (fetch)
origin git@github.com:FULANO/gittest.git (push)

# E seria (https://github.com/FULANO/gittest) para conexões via HTTPS.

# Para remover o origin use:
$› git remote rm origin

Com isso, nós apelidamos nosso repo, por padrão todos tem esse nome, facilita as coisas para nós, origin quer dizer que a origem dos arquivo (repositorio remoto).


Então vamos configurar o apelido do nosso repositório, e então criar um repositório via linha de comando:

# Configurando o apelido para nosso repo:
$› git remote add origin git@github.com:FULANO/gitcli.git

# Agora vamos criar um arquivo chamado 'README.md' para que possamos adicionar e commitar ele (tornando o novo repo ativo com isso):
$› touch README.md 1
# Agora adicione o arquivo ao Index:
$› git add README.md

# Agora faça o commit:
$› git commit -m "Commit Inicial"
[master (root-commit) 9bfc789] Commit Inicial
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 README.md

# Antes do push, veja uma coisa:
$› cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = git@github.com:FULANO/gitcli.git
fetch = +refs/heads/*:refs/remotes/origin/*

# Crie esse repo pela interface do git"

# Agora rode o push abaixo:
$› git push -u origin main
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 217 bytes | 217.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:FULANO/gitcli.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

# Agora rode o 'cat' de novo:
$› cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = git@github.com:FULANO/gitcli.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "main"]
remote = origin
merge = refs/heads/main

# O '-u' adiciona onde devemos por padrão fazer o push!


Add


O comando add é usado para adicionar conteúdo no INDEX, ele faz isso atualizando o INDEX com o conteúdo disponível na Working Dir.

OpçãoDescrição
-iAbre um menu interativo onde podemos trabalhar com arquivos dentro do INDEX.
Se apertar 3 (revert) vai remover arquivo do stage ou
Se apertar 4 (add untracked) vai adicionar o arquivo ao stage.
-p ou --patchPodemos escolher qual mudança vai em qual commit.

Vamos ver como funciona o -p, para isso preparei um arquivo:

### Não adicione o arquivo para usar o '-p':

# Com as mudanças feitas, faça:
$› git add -p README.md

O git vai nos perguntar algumas coisas, segue abaixo as opções:

y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
e - manually edit the current hunk
? - print help

Agora você só deve dar Y (yes) para o que quiser adicionar num commit separado, se der mais de Y essas mudanças vão no mesmo commit.

# Veja que tenho 2 arquivos iguais, um em staged e outro em working dir:
$› git status
No ramo main
Your branch is up to date with 'origin/main'.

Mudanças a serem submetidas:
(use "git restore --staged <file>..." to unstage)
modified: README.md

Changes not staged for commit:
(utilize "git add <arquivo>..." para atualizar o que será submetido)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md


# Veja o que temos de diferente em staged:
$› git diff --staged README.md
diff --git a/README.md b/README.md
index d32e280..dad631e 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,3 @@
-# Learngit
-
-
-
## Getting started

To make it easy for you to get started with GitLab, here's a list of recommended next steps.


# Veja o que temos de diferente em working dir:
$› git diff README.md
diff --git a/README.md b/README.md
index dad631e..4e5671b 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,6 @@ Already a pro? Just edit this README.md and make it your own. Want to make it ea

cd existing_repo
git remote add origin https://gitlab.com/FULANO/learngit.git
-git branch -M main
-git push -uf origin main


## Integrate with your tools
@@ -83,6 +81,3 @@ Show your appreciation to those who have contributed to the project.

## License
For open source projects, say how it is licensed.
-
-## Project status
-If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.

Dessa forma podemos fazer commits específicos para partes específicas do código.



Commit


A opção commit é usada para registrar mudanças no repositório. O git cria um novo commit (quando a opção commit for usada) que contém o conteúdo atual do index e fornece uma mensagem de log que descreve as mudanças realizadas.


Após isso o "pacote" do commit é enviado para HEAD, onde ficará até ser enviado para o servidor remoto. Lembre-se de que o último commit é etiquetado (tag) como HEAD, observe nos logs, o último sempre será HEAD, dessa forma conseguimos trabalhar de uma forma até que fácil.


Normalmente o processo de fazer um commit é bem simples, mas pode acontecer de você errar alguma coisa na descrição do commit ou simplesmente querer mudar, para isso vejamos alguma(s) forma(s) de fazer isso:

OpçãoDescrição
--amendSubstitui o último commit por um novo.

Façamos um teste agora:

# Faça o commit com algum erro na descrição:
$› git commit -m "Adicionando nova featureee verao 1"

# Verifique no log com está a descrição:
$› git log
commit 3a5f06c6a3027dc8f7856e0fc717f702d6690fe4 (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 10:29:38 2022 -0300

Adicionando nova featureee verao 1




# Agora vamos corrigir a descrição acima:
$› git commit --amend -m "Adicionando nova feature versao 1"
[main 5d39114] Adicionando nova feature versao 1
Date: Tue Oct 4 10:29:38 2022 -0300
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 features/teste_v1


# Verifique novamente o log para ver está a descrição agora:
$› git log
commit 5d39114df35aea12bf69f8f9c2c34cf774cde830 (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 10:29:38 2022 -0300

Adicionando nova feature versao 1

Como foi descrito, um novo commit é criado, perceba que o hash mudou, mas a mensagem está correta e pronta para ser enviada ao repositório remoto.


Isso ajuda bastante, mas e se eu quiser corrigir um commit mas ele não for o último commit? Nesses casos leia a seção do reset.



Pull


Usado para pegar o que está no repo remoto e sincronizar o repo local. O git pull executa em backend um git fetch origin com os parâmetros fornecidos e chama git merge origin/branch_name para mesclar os cabeçalhos de branch recuperados no branch atual.


Você usa ele quando seu repositório remoto possui arquivos que o repo local não tenha.



Push


A grosso modo pega todas as mudanças que estão em HEAD Dir e as envia para o servidor remoto, sua funcionalidade se extende para que junto ao envio de arquivos, outras coisas aconteçam.

OpçõesDescrição
-u ou --set-upstreamDefine a branch que vamos enviar os arquivos.
-f ou --forceForça a ação desejada.
-o (string)O mesmo que --push-option=(string).
Essa opção passa ações que o servidor deve tomar.
Quando essa opção não é usada, os valores configurados para a variável push.pushOption são usados.

A opção -o é mais encontrada quando usado com Gitlab para fornecer algumas opções ao servidor, lembrando que nos testes não obtive compatibilidade com o Github.

Mais detalhes podem ser encontrados aqui.

# Fazer um push numa outra branch (já criada anteriormente para não dar erro),
# e então fazer o pedido de merge com a branch default:
$› git push --set-upstream origin "nome da branch" -o merge_request.create

Ao fazer testes com merge_request.create ou pull_request.create no github, o pedido de merge não foi criado, tive que fazer manualmente, então só funciona no Gitlab.



LOGS


A opção log é usada para ver registros de eventos que ocorreram no repositório, normalmente envolvendo sempre os commit.


OpçãoDescrição
-NOnde N é um número. É usado para filtrar a quantidade de logs que será exibida.
-p (--)Faz a saída ser um pouco diferente do normal. A opção -- após o -p serve para separar revisões de patchs
--author=(nome)Usado para ver somente os logs de uma pessoa.
--onelineUsado para ver uma linha por commit.
shortlog -snMostra apenas a quantidade de commits feito por cada autor.
shortlogMostra um resumo dos logs.

Vamos dar uma olhada em como funciona essa opção:

# Ver os logs:
$› git log
commit bf2b32c4b4c985cb59e345554b14f05cf47b9fde (HEAD -> main, origin/main)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 20:06:38 2021 -0300

Add conteudo novo para o .gitignore

commit 49b9dbb31f46d7f2b8ef151696f8441a369e3350
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:59:32 2021 -0300

Add conteudo ao .gitignore

commit b024e117094716e4a156651bf6ff4b93dafd33ae
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:57:12 2021 -0300

Add .gitignore

commit 9bfc789eff8ae4598cc9b7d03ac058505992ca5d (master)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:09:17 2021 -0300

Commit Inicial

# Escolhendo a quantidade de logs na tela:
$› git log -2
commit bf2b32c4b4c985cb59e345554b14f05cf47b9fde (HEAD -> main, origin/main)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 20:06:38 2021 -0300

Add conteudo novo para o .gitignore

commit 49b9dbb31f46d7f2b8ef151696f8441a369e3350
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:59:32 2021 -0300

Add conteudo ao .gitignore

# Pesquisando por autor:
$› git log --author=AUTOR_NAME

# Vendo apenas 1 linha por commit:
$› git log --oneline
bf2b32c (HEAD -> main, origin/main) Add conteudo novo para o .gitignore
49b9dbb Add conteudo ao .gitignore
b024e11 Add .gitignore
9bfc789 (master) Commit Inicial

# Resumindo os logs:
$› git shortlog
FULANO (4):
Commit Inicial
Add .gitignore
Add conteudo ao .gitignore
Add conteudo novo para o .gitignore

# Mostrando a quantidade de commit por pessoas:
$› git shortlog -sn
4 FULANO


# Ver todas as mudanças que um arquivo sofreu, mostrando também o log e descrições:
$› git log -p -- VPS/sendnotify_fail2ban.sh
commit d89dd05cc2c20dfa988fdbbacb4ee148ed470a91 (HEAD -> main, origin/main, origin/HEAD)
Author: FULANO <FULANO@exemplo.br>
Date: Fri Sep 16 21:30:34 2022 -0300

Organizando

diff --git a/VPS/sendnotify_fail2ban.sh b/VPS/sendnotify_fail2ban.sh
deleted file mode 100644
index fef56c9..0000000
--- a/VPS/sendnotify_fail2ban.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/usr/bin/bash
-
-filev4="/root/bin/owncloud_block_v4"
-file_sshd="/root/bin/sshd_block_v4"
-
-IPs="$(iptables -nL f2b-owncloud | grep -i reject | awk '{ print $4 }')"
-IPs_sshd="$(iptables -nL f2b-sshd | grep -i reject | awk '{ print $4 }')"
-
-echo "$IPs" >> $filev4
-echo "$IPs_sshd" >> $file_sshd

commit e6b568341262e2b7d7780ec4a53cf2b0abb93d6d
Author: FULANO <39762901+FULANO@users.noreply.github.com>
Date: Fri Sep 16 21:14:35 2022 -0300

Create sendnotify_fail2ban.sh

diff --git a/VPS/sendnotify_fail2ban.sh b/VPS/sendnotify_fail2ban.sh
new file mode 100644
index 0000000..fef56c9
--- /dev/null
+++ b/VPS/sendnotify_fail2ban.sh
@@ -0,0 +1,10 @@
+#!/usr/bin/bash
+
+filev4="/root/bin/owncloud_block_v4"
+file_sshd="/root/bin/sshd_block_v4"
+
+IPs="$(iptables -nL f2b-owncloud | grep -i reject | awk '{ print $4 }')"
+IPs_sshd="$(iptables -nL f2b-sshd | grep -i reject | awk '{ print $4 }')"
+
+echo "$IPs" >> $filev4
+echo "$IPs_sshd" >> $file_sshd


SHOW


Com ele podemos ver o que foi mudado num commit, para isso você precisa do git log para coletar o hash.

$› git show 2ded7e936dfd0462897d4e49a43d1edc830ee474                                                                                commit 2ded7e936dfd0462897d4e49a43d1edc830ee474 (HEAD -> main, origin/main)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 20:16:46 2021 -0300

Acertando uma letra no gitignore

diff --git a/.gitignore b/.gitignore
index 39c3e7e..fe8b4e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,7 +4,7 @@
valores.txt
# Qualquer arquivo que tenha .txt (na raiz):
/*.txt
-# apenas o arquivo rm.log (na raiz):
+# Apenas o arquivo rm.log (na raiz):
/rm.log
# Qualquer coisa dentro de (log/):
logs/**


# Ver quais arquivos foram editados usando hash do log:
$› git show --name-only -r d89dd05cc2c20dfa988fdbbacb4ee148ed470a91
commit d89dd05cc2c20dfa988fdbbacb4ee148ed470a91 (HEAD -> main, origin/main, origin/HEAD)
Author: FULANO <FULANO@exemplo.br>
Date: Fri Sep 16 21:30:34 2022 -0300

Organizando

VPS/README
VPS/crontab/check_connections.sh
VPS/crontab/check_owncloud_block.sh
VPS/crontab/crontab
VPS/crontab/sendEmail.sh
VPS/crontab/sendnotify_fail2ban.sh
VPS/etc/fail2ban/filter.d/owncloud.conf
VPS/etc/fail2ban/jail.d/defaults-debian.conf
VPS/sendnotify_fail2ban.sh


DIFF


Usado para ver as mudanças antes de fazermos o commit. Para isso voce precisa ter arquivos com a tag unmodified.

# Mostra somente os arquivos:
$› git diff
diff --git a/README.md b/README.md
index 246ebcc..7938573 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
## Titulo 1
+Linha 1


# Informa apenas o nome do(s) arquivos que sofreram alteração e que estão
# em Working Dir:
$› git diff --name-only
README.md


# Ver o que mudou num arquivo que está em Working Dir:
$› git diff new
diff --git a/new b/new
index 3e75765..cd2ca46 100644
--- a/new
+++ b/new
@@ -1 +1,2 @@
new
+Add line 2

# Ver o que mudou num arquivo que está em Staged:
$› git diff --staged new
diff --git a/new b/new
index 3e75765..cd2ca46 100644
--- a/new
+++ b/new
@@ -1 +1,2 @@
new
+Add line 2


Rollback


Vamos ver como voltar os arquivos usando um commit que já foi feito, com isso podemos voltar num ponto específico e simular um rollback. Tenha cuidado com o merge entre o estado atual do repo e os arquivos que você voltou o estado deles.


Vamos ver algumas formas de fazer isso.


Checkout


Nesse caso a opção checkout é usada para fazer um rollback do arquivo, voltando ele para a mesma versão do Index. Se você der um git add... essa opção de rollback não vai surtir nenhum efeito.

# Arquivo original:
$› git status
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean

$› cat README.md
## Titulo 1


# Depois da alteração:
$› git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: README.md

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

$› cat README.md
Titulo 1
Linha 1

# Agora faça o rollback com o 'git checkout <arquivo>':
$› git checkout README.md
Updated 1 path from the index

$› cat README.md
## Titulo 1

Lembre-se: Isso só funciona com arquivos que não foram adicionados ao Index e que também não foram comitados.



Restore


Com o git restore (arquivo) nós podemos fazer o rollback de um arquivo que ainda não foi adicionado ao index (usando git add...). Essa técnica é idêntica ao git checkout (arquivo):

# Modifique o arquivo:
$› cat README.md
## Titulo 1
teste1

# Adicione ele ao index:
$› git add README.md

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

nothing to commit, working tree clean

# Olhando o arquivo:
$› cat README.md
## Titulo 1

Uma outra opção do restore é a --staged, usada para quando você adiciona um arquivo, com isso, o index é atualizado e o arquivo é marcado como staged e enviado para o estágio HEAD, não vou mostrar essa opção porque existe outra maneira de fazer isso, e vamos ver ela abaixo, mas fica a dica aqui.



Reset HEAD


O comando git reset HEAD (arquivo) é usado para fazer um reset da head atual para um estado específico, ou seja, normalmente o último commit é marcado como head, usando o comando git reset nós podemos mudar qual commit vai ser marcado como head e então fazer as mudanças necessárias.

Ao trabalhar com a nomeclatura HEAD aqui, não estamos nos referindo a área HEAD e sim a uma marcação de head que o commit ganha.


Basicamente ele desfaz um git add..., tirando o arquivo do HEAD e deixando ele em Working dir.

# Edite o arquivo:
$› cat novo_arquivo
apenas 1 linha


# Veja o status (atualmente em Working dir):
$› git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: novo_arquivo

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


# Adicione o arquivo:
$› git add novo_arquivo


# Veja o status de novo (Atualmente em INDEX, sabemos disso porque o arquivo está como staged):
$› git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: novo_arquivo


# Agora remova esse arquivo de INDEX:
$› git reset HEAD novo_arquivo
Unstaged changes after reset:
M novo_arquivo


# Veja que o conteúdo permanece o mesmo:
$› cat novo_arquivo
apenas 1 linha


# Agora veja o status, diferente do último status onde o arquivo estava em INDEX e como staged, agora ele está em 'Working dir', para ajudar você ai, você pode notar que o arquivo ficou vermelho (Working Dir) e fica verde (INDEX), isso nos ajuda.
$› git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: novo_arquivo

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


Reset baseado em commits


Nós podemos voltar o estado de um commit pra então fazer uma alteração naquele commit, para isso, temos que entender algumas sintaxes:

OpçõesDescrição
--softVolta o commit escolhido, o arquivo fica no ponto correto para refazer aquele commit. Somente precisa refazer o comando
git commit... novamente.
--mixedTambém volta para o commit escolhido, mas o arquivo fica como modified, com isso, é preciso dar o git add... e git commit... novamente.
--hardVolta o commit em si, é como se você nunca tivesse feito essa commit olhando para o repositório, mas esse commit continua registrado.

ATENÇÃO

Você sempre deve voltar um commit anterior daquele que deseja, se você voltar no commit exato que escolheu, vai voltar para as alterações dele, e isso não vai impedir que essas alterações sejam refeitas.

# Vamos ver nossos commits:
$› git log commit 83c9ef81becd31ad0fbc01b658651000a07d2b39 (HEAD -> main, origin/main)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 20:20:29 2021 -0300

escrevendo em README

commit 2ded7e936dfd0462897d4e49a43d1edc830ee474
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 20:16:46 2021 -0300

Acertando uma letra no gitignore

commit bf2b32c4b4c985cb59e345554b14f05cf47b9fde
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 20:06:38 2021 -0300

Add conteudo novo para o .gitignore

commit 49b9dbb31f46d7f2b8ef151696f8441a369e3350
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:59:32 2021 -0300

Add conteudo ao .gitignore

commit b024e117094716e4a156651bf6ff4b93dafd33ae
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:57:12 2021 -0300

Add .gitignore

commit 9bfc789eff8ae4598cc9b7d03ac058505992ca5d (master)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:09:17 2021 -0300

Commit Inicial

Vamos voltar um commit:

# Volte o 5° commit, ou seja, o commit onde alteramos apenas 1 letra em README, para isso vamos ter que voltar um commit antes, usando a hash: 'bf2b32c4b4c985cb59e345554b14f05cf47b9fde':
$› git reset --hard bf2b32c4b4c985cb59e345554b14f05cf47b9fde
HEAD is now at bf2b32c Add conteudo novo para o .gitignore

# Agora veja os logs:
$› git log
commit bf2b32c4b4c985cb59e345554b14f05cf47b9fde (HEAD -> main)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 20:06:38 2021 -0300

Add conteudo novo para o .gitignore

commit 49b9dbb31f46d7f2b8ef151696f8441a369e3350
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:59:32 2021 -0300

Add conteudo ao .gitignore

commit b024e117094716e4a156651bf6ff4b93dafd33ae
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:57:12 2021 -0300

Add .gitignore

commit 9bfc789eff8ae4598cc9b7d03ac058505992ca5d (master)
Author: FULANO <sysnetbreng@gmail.com>
Date: Sat Aug 28 19:09:17 2021 -0300

Commit Inicial

#### Tudo depois desse commit sumiu, tome cuidado com isso (mas até commitarmos de novo).

# Volte para o segundo commit exato:
$› git reset --mixed b024e117094716e4a156651bf6ff4b93dafd33ae
Unstaged changes after reset:
M .gitignore
M README.md

$› git status
On branch main
Your branch is behind 'origin/main' by 4 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)

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: .gitignore
modified: README.md

no changes added to commit (use "git add" and/or "git commit -a")
# Perceba que temos que adicionar os arquivos e commitar para aplicar esse commit de novo!

# Apague tudo aqui dentro:
$› yes | rm -r *
$› rm .gitignore

# Faça um 'git pull' para baixar tudo de novo (com isso sincronizamos tudo de novo):
$› git pull -f
Updating b024e11..83c9ef8
Fast-forward
.gitignore | 12 ++++++++++++
README.md | 1 +
2 files changed, 13 insertions(+)

# Volte esse commit apenas como soft:
$› git reset --soft b024e117094716e4a156651bf6ff4b93dafd33ae

$› git status
On branch main
Your branch is behind 'origin/main' by 4 commits, and can be fast-forwarded.
(use "git pull" to update your local branch)

Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: .gitignore
modified: README.md

Fazendo um reset de verdade:

# Faça o reset:
git reset --hard bf2b32c4b4c985cb59e345554b14f05cf47b9fde

# Modifique o nome do arquivo que queira fazer o rollback:
$› mv .gitignore gitignore

# Faça o 'git pull':
$› git pull
Updating bf2b32c..c3ac01f
Fast-forward
.gitignore | 3 ++-
README.md | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)

# Apague o arquivo da versão nova:
$› rm .gitignore

# Renomeie o arquivo antigo para o mesmo nome:
$› mv gitignore .gitignore

# Veja o status:
$› git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: .gitignore

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

# Agora faça o add, commit e push:
$› git add .

$› git commit -m "Acertando o gitignore"
[main b7a8a47] Acertando o gitignore
1 file changed, 1 insertion(+), 2 deletions(-)

$› git push origin main
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 6 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 320 bytes | 320.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:FULANO/gitcli.git
c3ac01f..b7a8a47 main -> main

Você pode apoós o reset, fazer o pull e incluir todo os registros do repo, somente modificando depois disso, basicamente você volta o repo naquele commit desejado, salva os arquivos que você quer, faz o pull e após isso adiciona e commita de novo.

Mas existe outra forma que pode acabar com o registro do repo, após qualquer um desses reset, você faz um git push -f (forçado), assim é como se tudo depois desse commit nunca tivesse existido.

Tome cuidado com isso.



Revert


O git revert vai reverter um commit em específico, ou seja, tudo que foi modificado no commit em questão será desfeito. O Git faz isso criando um novo commit com a reversão.


# Veja os commits importantes:
$› $ git log
commit 08a7e0f60f081b6b522434d72bca4e1bd6408623 (HEAD -> main, origin/main, origin/HEAD)
Author: bsilva <bsilva@registro.br>
Date: Tue May 14 19:27:25 2024 -0300

novos arquivos

commit 3908a6141199a6fdb681effb85a7bc054f84c18a
Author: bsilva <bsilva@registro.br>
Date: Tue May 14 19:26:35 2024 -0300

Alterando o conteudo do arquivo da alice


# Veja o que foi adicionado no commit '3908a6141199a6fdb681effb85a7bc054f84c18a':
$› git show 3908a6141199a6fdb681effb85a7bc054f84c18a
commit 3908a6141199a6fdb681effb85a7bc054f84c18a
Author: bsilva <bsilva@registro.br>
Date: Tue May 14 19:26:35 2024 -0300

Alterando o conteudo do arquivo da alice

diff --git a/.public-keys/alice b/.public-keys/alice
index 4d2ae93..15c3dc1 100644
--- a/.public-keys/alice
+++ b/.public-keys/alice
@@ -34,3 +34,5 @@ l41n6lf6qu3aPvCe1Qcn8eWWKU2mMJUCnzZRA4G81ziClJbld+INjySU+13ufoaO
7qZbqZZnw9hKWPD5GD/AItqwjPPVPGaDIn1MSNU12/gMzM7mZWl47wD9TKBnwSX7
=BxCd
-----END PGP PUBLIC KEY BLOCK-----
+
+alice


# Veja o conteúdo do arquivo:
$› cat .public-keys/alice
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
=BxCd
-----END PGP PUBLIC KEY BLOCK-----

alice


# Agora vamos reverter as alterações desse commit específico:
$› git revert 3908a6141199a6fdb681effb85a7bc054f84c18a
[main c2196b3] Revertendo alterações no arquivo alice
1 file changed, 2 deletions(-)

# Veja o conteúdo do arquivo:
$› cat .public-keys/alice
-----BEGIN PGP PUBLIC KEY BLOCK-----

mQENBGNAiAYBCACmOX8mIZak0IBxi15X20EU46uT6ZDBGehDkh+5ECcgnGLIV1+F
XbM+LOxeuDcKDS/2ShDoyDoVulwNEhN1m5NR2JCLM0Myeo+Mxy6xdtUMmXB4+0Ki
1CeST+yuQE/zZw3P7G0z9SuxL9bcL8aRIZjEcvWfeZH9XLBndgdu6SSJOnpDBcC7
VjLKfMu7vAbIGZpJddVjlckpAZltn1djrtLDQQ/Nv85fE3LDgzniv0FgeTBrBiVu
Um4w6Cx/oSLUO9g9AjTKuLgiKrCnQKhlwV8eECjwTs0qfBnpV8x8sZEaj4uRvhtF
qKfDherDQ0QHoNLWVXmPo6nC/itPbOmLdnW5ABEBAAG0HmFsaWNlIFRlc3RlciA8
YWxpY2VAZ21haWwuY29tPokBTgQTAQoAOBYhBLrsqF0AboDe8alC6TBJOqqm74wV
BQJjQIgGAhsvBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEDBJOqqm74wVLFAH
/10fXARSH+zkEJnwD9JYjqedvsx6KAJbeiGlrH71+aPKS2HAr4VDVNSK3LtO4wDK
6pI6tCNDpOf/1vqFN2q/AiBCUoMRZ6j1i9+9wDr6eIsClQM7pwLFQhwRP0s/afrB
mYM8pmtc+Fhpu3XLX3ZC15F7D4TCUy4TlHagwlGr1/e0BxOWa1ZJ4cinoZaBI+S+
DspFROXcCxJk3YO1+4l3tK5SKJpvp7TuAjzy+Tqx3G9XXKYgB2g+Nsafzi8mxAju
8dDzXiSW628aYrqBFN/D0pKmyFbOFWHlURPAAABs75muKtYYEUJmMh66AwPtilqv
T/d1U/4ytm3VyQiS75bvWtq5AQ0EY0CIBgEIAO+XYOZK10fD7BOwdXToM1/JlIaQ
73pxqD43z2mVVbKM8FyENBJOQGWX0vmVvl3tI1lYDp7d0xwmArfAbanh3boRsbp2
ACpsoN7WZrpnhsXTisEEXeTCeuctMBTv3V1sOdeokU9UjpGHJnqlrdm6p84eB7YO
KckPoZBzpYjgyf9p+0xaIyXae6F68CRzn05Iy+S42Gww2g93E1CJ+VKPllUk4ZOQ
BbS6vhb2lhpIh/N4jr0Sk1Ux2OKY1s5WUOw6NSAGSPSz5PV2ES8SwkNClXqgN53u
jVFNFqU2Mkm45ui44GTLlxgEWeseFMa87KN2Nu58FU7FIWLV9hAzKsOFdekAEQEA
AYkCbAQYAQoAIBYhBLrsqF0AboDe8alC6TBJOqqm74wVBQJjQIgGAhsuAUAJEDBJ
Oqqm74wVwHQgBBkBCgAdFiEEU5JhiX2ObTjqyrMwrkCMU8PhEh0FAmNAiAYACgkQ
rkCMU8PhEh2/ogf+OGluPNG98Xv/w2V5xYP4SjB9A6/ePAJmL1RTyIYDDtZyZYki
MOQdkmII9GSrvEZWfw4RMonHxmS3MRlQAxqcvIvTg7dB72nMxOh8nXJsoXYXWnJg
Fxnc2/HmSsK1lQ1GRY9WQKgoK7UtjK89ALwxF3hjwkZgOjZI50J5kg+1lHxsgGMB
38UtzAY98ytuSQAj/Kb6om65XGr0vhmqRPS3luQAQkF/ypGzJazwP075rkKOF8xB
GQtcnT77y9/N/s0hl354XlZrb6n4FbTv60ypWvRxO/2tgmTa+9j+KRuoCmXXxRXc
IsB5A/UrJhdHLOQHw9cOb7jE9ks5teuiBCdkhoNPB/9JMhSr6ZGMy3sd0QuhJHJY
t6m0wfgw56PNsDb9xU8cvMAIPMC9WW5My1tX2X1sZak2nYwqD/u+sTatXHTKCSKr
cZxD/pRNZF/qNtKap6dzv0sQAlh12zuPSGCq8atdw9ahIqddeCtFRSrr2N4bw6YA
2qEiYOT99GiymC0eiDmzfHj+4XkEm669vel/awKHDCBV1n68GmyhJQCaC0yqJCvj
l41n6lf6qu3aPvCe1Qcn8eWWKU2mMJUCnzZRA4G81ziClJbld+INjySU+13ufoaO
7qZbqZZnw9hKWPD5GD/AItqwjPPVPGaDIn1MSNU12/gMzM7mZWl47wD9TKBnwSX7
=BxCd
-----END PGP PUBLIC KEY BLOCK-----

# Veja os commits novos:
$› git log
commit c2196b3e595732bd2c52b6caf48228d74293b32f (HEAD -> main)
Author: bsilva <bsilva@registro.br>
Date: Tue May 14 19:42:20 2024 -0300

Revertendo alterações no arquivo alice

This reverts commit 3908a6141199a6fdb681effb85a7bc054f84c18a.

commit 08a7e0f60f081b6b522434d72bca4e1bd6408623 (origin/main, origin/HEAD)
Author: bsilva <bsilva@registro.br>
Date: Tue May 14 19:27:25 2024 -0300

novos arquivos

commit 3908a6141199a6fdb681effb85a7bc054f84c18a
Author: bsilva <bsilva@registro.br>
Date: Tue May 14 19:26:35 2024 -0300

Alterando o conteudo do arquivo da alice


Git Ignore


Existe um arquivo oculto que pode ser colocado no repo para que o Git ignore arquivos e pastas, podemos usar alguns coringas para melhorar e filtrar esse conteúdo da visao do Git, com isso nós conseguimos impedir que o Git envie eles para o repo remoto.


Vamos ver um exemplo de um .gitignore:

#################################
##### Exemplo de .GitIgnore #####
#################################
#
# Ignora o arquivo valores.txt não importa onde ele esteja:
valores.txt
# Qualquer arquivo que tenha .txt (na raiz):
/*.txt
# apenas o arquivo rm.log (na raiz):
/rm.log
# Qualquer coisa dentro de (log/):
logs/**
# Qualquer coisa que tenha log dentro (*/log):
**/log
# Cria uma exceção:
!teste.txt


Checkout


Usado para obter uma branch específica para que possamos fazer as alterações, seu uso é muito similar a opção branch. Com algumas diferenças que foi explicado acima.


OpçãoDescrição
-b (nome)Cria uma branch caso não exista -b e muda para essa branch.
-b branch_name origin/branch_nameCria uma branch caso não exista -b, muda para essa branch e ainda faz o sync com a branch remota.
-t origin/branch_nameSincroniza ma branch remota localmente.
git checkout (nome)Apenas muda para a branch.
git checkout (arquivo)Volta o arquivo para a mesma versão do Index.


Branch


As Branchs (ramos ou ramificações nesse caso), são como linhas do tempo paralelas (pensamos em multiversos), mas aqui temos uma linha do tempo que é a original, com isso, todas as linhas do tempo são ramificações de apenas 1 linha do tempo, a grande sacada aqui é que em qualquer momento, nós podemos mesclar qualquer linha do tempo paralela com a linha original, fazendo com que 2 linhas do tempo se tornem 1, e que essa fusão crie uma nova linha do tempo original e não uma paralela.


Veja a imagem abaixo:

branch

Cada ramo que sai da linha do tempo original é uma Branch, onde toda as ramificações estão ligadas a linha do tempo original em algum ponto especifico, mas em qualquer momento, podemos pegar essas linhas do tempo paralelas e mesclar com a linha do tempo original.


OpçãoDescrição
git branchMostra todas as Branchs, a branch com * indica a Branch atual.
git branch (name)Cria uma Branch.
-aMesma coisa acima.
-d (nome)Apaga uma Branch.
-D (nome)Apaga uma Branch a força.
-M (novo nome)Renomeia a branch atual. Pode ser -m também.
--no-mergedExibe as Branchs ainda não mescladas.
--mergedExibe as Branchs que foram mescladas.

Outro método de trabalhar com Branchs é através do comando checkout:

ComandoDescrição
git checkout -b (nome da Branch)Cria uma nova branch e ja entrar nela.
git checkout (nome da Branch)Mudar da branch atual para outra branch.
git branch (nome da Branch)Apenas cria uma branch.
git push origin (nome da Branch)Fazer um push dos arquivos da branch atual em outra branch (ela já deve existir).


Branch Pai e Filho


Cada branch possui um pai ou mais de um, quando uma branch possui um pai, ela é naturalmente filha daquela branch. Cuidado ao mesclar uma branch que tem mais de um Pai, isso fará com que ao mesclar essa branch todos os pais dela também serão mesclados. Para efeito didático veja o exemplo abaixo:

git_parents_im1

A imagem acima demonstra que a branch master está apontando para o commit b3c0366. Agora vamos criar uma outra branch chamada mudar_versao e vamos ver qual é o pai dela (farei modificações nessa branch):

# Liste os logs mostrando os pais de cada commit:
$ git log --oneline --decorate --parents
30a4131 731e69e (HEAD -> mudar_versao) add feature em mudar_versao
731e69e b3c0366 Mudando versao para 2 em branch mudar_versao
b3c0366 (master) Primeiro commit para arquivo de versao na branch master

Usamos o parâmetro --parents para ver os commits com seus respectivos pais.

A primeira coluna é o commit em si. A segunda coluna é o commit pai do qual esse commit se originou, já a terceira é a mensagem do commit (primeira coluna).


A primeira linha mostra o commit da qual nossa branch se originou vinda da branch master (b3c0366), depois fiz um commit dentro da nova branch, esse commit tem como pai o commit da branch master que originou a nova branch (731e69e b3c0366) e por fim eu adicionei um arquivo (commit 30a4131) que tem como pai o commit anterior da nossa branch (731e69e, ). Para facilitar a visualização veja a imagem abaixo:

git_parents_im2


Agora vamos criar outra branch, essa nova branch deve ser originada da branch mudar_versao, sendo assim, essa branch (mudar_versao) vai ter um filho e a nova branch (mudar_versao2) vai ter um pai.

# Liste os logs mostrando os pais de cada commit:
$ git log --oneline --decorate --parents
be73a8f 6a6bc6a (HEAD -> mudar_versao2) add revisao em mudar_versao2
6a6bc6a e41cb4a add new_file em mudar_versao2
e41cb4a 30a4131 Mudando versao para 3 em branch mudar_versao2
30a4131 731e69e (mudar_versao) add feature em mudar_versao
731e69e b3c0366 Mudando versao para 2 em branch mudar_versao
b3c0366 (master) Primeiro commit para arquivo de versao na branch master

Veja a imagem abaixo para facilitar o entendimento:

git_parents_im3

Podemos ver que a branch mudar_versao2 se origina da branch mudar_versao no commit 30a4131 que por sua vez se origina da branch master no commit b3c0366.

É possível ver qual branch pertence um commit com o comando abaixo:

$ git name-rev ef760ed
ef760ed mudar_versao

$ git name-rev 9822bf8
9822bf8 versao3

$ git name-rev 56aa2fa
56aa2fa master

# Um outro comando que podemos rastrear os pais é:
$ git log --oneline --decorate --abbrev-commit master...mudar_versao2 --parents
5ddbe39 7d9b277 (mudar_versao2) add revisao em mudar_versao2
7d9b277 47e93d1 add new_file em mudar_versao2
47e93d1 0faac7e Mudando versao para 3 em branch mudar_versao2
0faac7e 56aa2fa Mudando versao para 2 em branch mudar_versao

# Ver os commits de uma branch:
$ git log --oneline --decorate --abbrev-commit mudar_versao

Agora faça o merge da branch mudar_versao2 com a master e veja que mudar_versao será mesclada junto, porque ambas apontam para o mesmo commit inicial (b3c0366).

### primeiro veja os arquivos e a versão que temos em cada branch:

## Na branch mudar_versao2:
$ ls
feature new_file revisao version

$ cat version
3


## Na branch mudar_versao:
$ ls
feature version

$ cat version
2

## Na master:
$ ls
version

$ cat version
1


# Mude para a branch master:
$ git checkout master
Switched to branch 'master'

# Veja os logs:
$ git log
commit b3c036684e34757315e7d0d9c301dc0f123346dd (HEAD -> master)
Author: FULANO <FULANO@exemplo.br>
Date: Mon Oct 24 17:14:37 2022 -0300

Primeiro commit para arquivo de versao na branch master


# Faça o merge:
$ git merge mudar_versao2 -m "Merging mudar_versao2 into master"
Updating b3c0366..be73a8f
Fast-forward (no commit created; -m option ignored)
feature | 1 +
new_file | 0
revisao | 0
version | 2 +-
4 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 feature
create mode 100644 new_file
create mode 100644 revisao

# Veja o valor de version (1 = master, 2 = mudar_versao e 3 = mudar_versao2):
$ cat version
3

# Veja os logs:
$ git log --oneline --decorate --parents
be73a8f 6a6bc6a (HEAD -> master, mudar_versao2) add revisao em mudar_versao2
6a6bc6a e41cb4a add new_file em mudar_versao2
e41cb4a 30a4131 Mudando versao para 3 em branch mudar_versao2
30a4131 731e69e (mudar_versao) add feature em mudar_versao
731e69e b3c0366 Mudando versao para 2 em branch mudar_versao
b3c0366 Primeiro commit para arquivo de versao na branch master

# Veja os arquivos:
$ ls
feature new_file revisao version

# Liste as branchs mescladas e não mescladas:
$ git branch --merged
* master
mudar_versao
mudar_versao2

# Essa não vai exibir nada:
$ git branch --no-merged

Perceba que ao mesclar mudar_versao2, foi automaticamente mesclado a branch mudar_versao, mas cabe um parênteses aqui, só serão mesclados branchs dessa forma desde que todas possuam os mesmos arquivos, por exemplo, temos arquivos em comuns entre as duas branchs, além de serem o mesmo arquivo, possuem o mesmo conteúdo, mas a branch mudar_versao2 está a frente de mudar_versao, por isso a mesclagem automática. Caso as brenchs sejam diferente não será mesclado, veja abaixo:

# Adicionei outro arquivo em mudar_versao, veja os Logs:
$ git log --oneline --decorate --parents
043fd23 30a4131 (HEAD -> mudar_versao) feature agora é f2 em mudar_versao
30a4131 731e69e add feature em mudar_versao
731e69e b3c0366 Mudando versao para 2 em branch mudar_versao
b3c0366 (master) Primeiro commit para arquivo de versao na branch master

A imagem abaixo representa o novo estado das nossas branchs:

git_parents_im4

Agora faça o merge:

### primeiro veja os arquivos e a versão que temos em cada branch:

## Na branch mudar_versao2:
$ ls
feature new_file revisao version

$ cat feature
f1

$ cat version
3


## Na branch mudar_versao:
$ ls
feature version

$ cat feature
f2

$ cat version
2

## Na master:
$ ls
version

$ cat version
1


# Mude para a branch master:
$ git checkout master
Switched to branch 'master'

# Veja os logs:
$ git log
commit b3c036684e34757315e7d0d9c301dc0f123346dd (HEAD -> master)
Author: FULANO <FULANO@exemplo.br>
Date: Mon Oct 24 17:14:37 2022 -0300

Primeiro commit para arquivo de versao na branch master


# Faça o merge:
$ git merge mudar_versao2 -m "Merging mudar_versao2 into master"
Updating b3c0366..be73a8f
Fast-forward (no commit created; -m option ignored)
feature | 1 +
new_file | 0
revisao | 0
version | 2 +-
4 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 feature
create mode 100644 new_file
create mode 100644 revisao

# Veja o valor de version (1 = master, 2 = mudar_versao e 3 = mudar_versao2):
$ cat version
3

# Veja os logs:
$ git log --oneline --decorate --parents
be73a8f 6a6bc6a (HEAD -> master, mudar_versao2) add revisao em mudar_versao2
6a6bc6a e41cb4a add new_file em mudar_versao2
e41cb4a 30a4131 Mudando versao para 3 em branch mudar_versao2
30a4131 731e69e add feature em mudar_versao
731e69e b3c0366 Mudando versao para 2 em branch mudar_versao
b3c0366 Primeiro commit para arquivo de versao na branch master

# Veja os arquivos:
$ ls
feature new_file revisao version

$ cat feature
f1

$ cat version
3

# Liste as branchs mescladas e não mescladas:
$ git branch --merged
* master
mudar_versao2

# Veja que agora tem uma branch:
$ git branch --no-merged
mudar_versao

Isso acontece porque o arquivo feature tem uma versão diferente do arquivo que está branch mudar_versao, sendo assim, só vão ser mesclados os arquivos de branchs que são pais da branch que vamos mesclar e que possuem o mesmo arquivo/conteúdo.



Merge


Usado para mesclar ou fundir uma Branch com a branch atual. Existem dois tipos de merge, o local e o remoto.

  • Remoto

    Ao enviar os arquivos para o servidor remoto (fazer o push), é enviado numa branch que não é a príncipal e após isso é feita a solicitação de mesclagem entre as duas Branch.

    Para unir uma branch com a branch main nós temos que fazer uma requisição conhecida como Merge Request - MR no Gitlab e conhecia como Pull Request - PR no Github. Com isso uma branch pode se mesclar com a branch main caso seja possível (pode acontecer de ter incompatibilidades entre arquivos).

    A branch remota é diferenciada da local pelo origin em seu nome, por exemplo, a branch origin/main significa que estamos falando da branch main que está remotamente, já a branch main (sem o origin) estamos falando da branch local.


  • Local

    São branchs que existem apenas na sua Working Tree, uma branch pode ser remota (existir no repositório remoto) e também existir localmente. Nós primeiros editamos nas branchs Locais (fazendo elas ficarem a frente da respectiva branch remota) e então enviamos para o repositório remoto que fará um merge entre a branch local com a remota.

Antigamente a branch original era chamada master, mas por causa do nome (mestre) e após a morte brutal de George Floyd e os protestos Black Lives Matter, o Git resolveu mostrar seu apoio à comunidade negra, abandonando termos não inclusivos como master, slave, black list e whitelist, sendo assim, o nome para se remeter a branch original é main.



O comando é bem simples:

# Fazer merge de branchs localmente:
$ git merge branch_name -m "Merge BRANCH into another BRANCH"

# Fazer merge de branch local com a remota:
$ git merge origin/branch_name -m "Merge BRANCH into another BRANCH"


Pipeline


O Pipeline está diretamente ligado a CI/CD, que normalmente se refere a Integração Contínua (Continuous Integration - CI) e Entrega Contínua (Continuous Delivery - CD), em outras palavras, são mecanismos de automatizar o deploy e o build de uma aplicação.


A Integração Contínua é a prática de mesclar os códigos que estão sendo gerados pelos devs. O merge geralmente ocorre várias vezes ao dia em um repositório compartilhado. De dentro do repositório ou ambiente de produção, a construção e os testes automatizados são realizados para garantir que não haja problemas de integração e a identificação antecipada de quaisquer problemas.


A Entrega Contínua acrescenta que o software pode ser liberado para produção a qualquer momento, muitas vezes empurrando automaticamente as alterações para um sistema de teste. A Implantação Contínua vai além e leva as alterações para a produção automaticamente.


Já o pipeline é o tão conhecido na Arquitetura de Computadores, que vem para tornar essa automatização mais rápida e melhorar o processamento, caso você não saíba o conceito de Pipeline, vou deixar aqui um link para consultar.


Para usar GitLab CI/CD, tudo o que você precisa é um repositório Git com arquivos funcionais (não basta colocar qualquer coisa), o teste e implantação precisa ser especificados em um arquivo chamado .gitlab-ci.yml, localizado na raiz de seu repositório. Um GitLab Runner, um arquivo escrito em Go, executará as tarefas especificadas no arquivo YAML usando uma API para se comunicar com o GitLab.


O administrador do GitLab pode configurar runners compartilhados para execução em vários projetos, e você pode configurar o seu próprio por projeto. Vou deixar abaixo um exemplo do meu gitlab-ci que faz o deploy do Docusaurus 2 no Gitlab Pages.


image: node:latest

cache:
paths:
- node_modules/
- public/
- .cache/

before_script:
- yarn install
- yarn upgrade @docusaurus/core@latest @docusaurus/init@latest

test:
stage: test
script:
- yarn install
- rm -r node_modules/prism-react-renderer/themes/dracula
- cp -r .theme/dracula node_modules/prism-react-renderer/themes/
- yarn run build
except:
- main

pages:
stage: deploy
script:
- rm -r public
- rm -r node_modules/prism-react-renderer/themes/dracula
- cp -r .theme/dracula node_modules/prism-react-renderer/themes/
- yarn run build
- mv build public
artifacts:
paths:
- public
only:
- main


ISSUE


Todas as alterações no GitLab começam com uma issue. As issue podem permitir que você, sua equipe e seus colaboradores compartilhem e discutam propostas antes e durante sua implementação. No entanto, eles podem ser usados para uma variedade de outros fins, personalizados de acordo com suas necessidades e fluxo de trabalho.


As issue estão sempre associados a um projeto específico, mas se você tiver vários projetos em um grupo, também poderá ver todos as issue coletivamente no nível do grupo.


Quem está mais acostumado com Github, costuma ver bem mais issue associadas a um bug ou falha de software, onde normalmente as pessoas notificam os Devs para correção.



Tag


É usado para marcar um ponto específico no tempo em uma branch (Com base nos commits).


OpçãoDescrição
git tagLista todas as tags.
git tag (name) (commit sha)Cria uma tag com um nome para a branch referente ao hash de commit.
git tag -a (name) (commit sha)Mesma coisa acima, mas coloca um comentário na tag.
git tag -d (name)Remove uma tag.

# Criando uma tag para o primeiro commit:
$› git tag first_tag 1d19a80749a7ddda6df8e324230b902fe4e8b120

# Listando:
$› git tag
first_tag

# Ao ver os logs, podemos ver as tags agora:
$› git log
commit 5da77485444e03f491edccebcbf468406f9045dd (HEAD -> main, tag: second_tag, origin/main, origin/HEAD)
Author: FULANO <sysnetbreng@gmail.com>
Date: Fri Sep 3 11:06:33 2021 -0300

novo commit depois de reset hard

commit 1d19a80749a7ddda6df8e324230b902fe4e8b120 (tag: first_tag)
Author: FULANO <39762901+FULANO@users.noreply.github.com>
Date: Tue Jul 6 15:29:38 2021 -0300

Initial commit


Rebase


É usado para reaplicar commits de uma outra maneira, seu uso é bem abrangente. Se a branch for especificada, o git rebase vai fazer um git switch branch antes de fazer qualquer outra coisa. Caso contrário, ele permanece no branch atual.


É muito usado para simplificar o histórico de uma branch enquanto mescla ela com outra branch, dessa forma temos um log mais limpo, mas em contra partida vamos perder algumas informações no processo.



Rebase vs Merge


Uma coisa que devemos ficar atentos é que quando usamos o merge ele vai manter um registro completo do que ocorreu em nossa branch, mas os commits de merge também serão exibido e vão poluir e deixar mais complicado tarefas como revisar o código novo.


Já o rebase simplifica o histórico, mas perdemos informação sobre nossa branch e alguns commits são reescritos. No caso de conflitos, as coisas ficam ainda mais complicadas.



Git stash


O git stash é um comando no Git que permite salvar temporariamente (ou "esconder", que seria "stashe") as mudanças que fezemos no repositório Local (mas que ainda não foram commitadas), as mudanças são armazenamento em uma área temporária. Isso pode ser útil quando precisamos mudar de branch ou realizar outras operações, mas quando não queremos commitar as alterações locais.


Quando executamos git stash, o Git salva as alterações fora da Working Dir, permitindo que a gente reverta temporariamente para o estado do seu último commit, ou seja, após executar git stash as edições Locais vão ser salvas fora da Working Dir e o estados dos arquivos será exatamento o mesmo do último commit.


Depois de rodar o git stash e fazer o que precisamos, temos que tirar os arquivos da área temporária e voltar elas para o Working Dir. Para fazer isso nós usamos git stash apply ou git stash pop, com uma pequena diferença:

  • git stash apply
    Retira os arquivos da área temporária e volta eles para o Working Dir, mas mantém uma cópia deles na área temporária. Você pode recuperar essa versão várias vezes.

  • git stash pop
    Também retira os arquivos da área temporária e volta eles para o Working Dir, mas não mantém uma cópia deles na área temporária. Isso é útil quando você não precisa mais manter o stash após aplicar as mudanças.


Como exemplo de uso, veja um exemplo real aqui.



Cheat sheet


Segue abaixo um apanhado de comandos que podem ser úteis.



Remover uma branch remota


Vamos remover uma branch que está no repositório remoto.

$ git push origin :branch_test
To gitlab.com:FULANO/learngit.git
- [deleted] branch_test


Mudar a descrição de um commit - Git reset


Vamos mudar a descrição de um commit que não seja o último commit (head), para isso o commit ainda está em HEAD, ou seja, não foi enviado para o servidor remoto.

#### O arquivo ainda não foi enviado para o servidor remoto!

# Vejamos os arquivos em HEAD:
$› git log ↵ 128
commit 723cb476bde1e48e3602a717c1d2a452734b1469 (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 10:40:47 2022 -0300

Adicionando nova feature2 versao 1

commit d997566ce0ebb53ecac488b0e3a2b63e968c3593
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 10:40:38 2022 -0300

Adicionando nova feature1 versao 1

commit 12b4f121b33bd3197e9d0771bfac52f697e81856
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 10:40:23 2022 -0300

Adicionando nova feature versao 1


# Eu quero mudar o commit do meio (feature 1), vamos nos certificar
# de mudar o arquivo certo:
$› git show --name-only --oneline HEAD~1
d997566 Adicionando nova feature1 versao 1
feature1/teste_v1


# Agora vamos mudar o commit (lembrando que poderia fazer usando o HASH):
$› git reset --soft HEAD~1


# Veja o estado do arquivo (com isso nenhuma modificação é perdida):
$› git status
No ramo main
Seu ramo está à frente de 'origin/main' por 2 submissões.
(use "git push" to publish your local commits)

Mudanças a serem submetidas:
(use "git restore --staged <file>..." to unstage)
new file: feature2/teste_v1


# Agora mude o commit:
$› git commit -m "Adicionando nova feature1 versao 1 para a equipe de dev"

# Pronto, commit acertado sem alterar o conteúdo do arquivo.


Mudar a descrição de um commit - Git rebase


A forma demonstrada acima funciona mas tem outra maneira de fazer usando o git rebase que é até mais fácil e interativa, para isso vou começar a adicionando mais três arquivos.


Existem alguns detalhes que devemos conhecer antes de nos aprofundar nisso:

OpçãoDescrição
squashVai juntar todos os commits dentro de um único commit (muito útil).
rewordVai apenas mudar a mensagem do commit, mantendo em commits separados.
editMuda o HEAD para outro commit, assim podemos mudar a descrição:
git commit --amend -m "mensagem nova"
E depois informamos que finalizamos a mudança com:
git rebase --continue


Fazendo rebase com a opção edit


#### O arquivo ainda não foi enviado para o servidor remoto!

# Veja os logs:
$› git log
commit 8161420b86c25156cb0ee76c18e25641af01a2b5 (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:33:04 2022 -0300

Adicionando nova feature2 versao 2

commit 55a5be1cdeb1021d7ccb244970f43489dddef471
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:56 2022 -0300

Adicionando versao 2 para a feature1

commit 80a1b8614070bf6b1073ea6865fb741b33877502
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:47 2022 -0300

Adicionando nova features versao 2


## Agora vamos mudar o HEAD para '55a5be1' e mudar a mensagem:
$› git rebase -i

## Agora mude de 'pick' para 'edit' para
## mudar apenas a mensagem do commit, você não deve mudar o primeiro commit,
## se quiser mudar ele use --amend e não rebase, vejamos o nosso exemplo abaixo:

pick 80a1b86 Adicionando nova features versao 2
edit 55a5be1 Adicionando versao 2 para a feature1
pick 8161420 Adicionando nova feature2 versao 2

## Depois salve a saia!

## Após isso o próprio git nos dirá o que temos que fazer:
$› git rebase -i
Stopped at 55a5be1... Adicionando versao 2 para a feature1
You can amend the commit now, with

git commit --amend

Once you are satisfied with your changes, run

git rebase --continue


# Mude a descrição:
$› git commit --amend -m 'Nova versao para a feature 1 - v2'
[detached HEAD 9263801] Nova versao para a feature 1 - v2
Date: Tue Oct 4 13:32:56 2022 -0300
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 feature1/teste_v2


# Agora informa ao git que finalizamos as edições:
$› git rebase --continue
Successfully rebased and updated refs/heads/main.


# Reveja os logs:
$› git log
commit 499824e9365cbdec0f3d30c23bfc06f3330d471f (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:33:04 2022 -0300

Adicionando nova feature2 versao 2

commit 92638015d0af92d5abd584ad06b625a0e6a5f6e2
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:56 2022 -0300

Nova versao para a feature 1 - v2

commit 80a1b8614070bf6b1073ea6865fb741b33877502
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:47 2022 -0300

Adicionando nova features versao 2


Fazendo rebase com a opção reword


#### O arquivo ainda não foi enviado para o servidor remoto!

# Veja os logs:
$› git log
commit 499824e9365cbdec0f3d30c23bfc06f3330d471f (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:33:04 2022 -0300

Adicionando nova feature2 versao 2

commit 92638015d0af92d5abd584ad06b625a0e6a5f6e2
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:56 2022 -0300

Nova versao para a feature 1 - v2

commit 80a1b8614070bf6b1073ea6865fb741b33877502
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:47 2022 -0300

Adicionando nova features versao 2


## Agora vamos mudar o HEAD para '499824e' e mudar a mensagem:
$› git rebase -i

## Agora mude de 'pick' para 'reword' para
## mudar apenas a mensagem do commit, você não deve mudar o primeiro commit,
## se quiser mudar ele use --amend e não rebase, vejamos o nosso exemplo abaixo:

pick 80a1b86 Adicionando nova features versao 2
pick 9263801 Nova versao para a feature 1 - v2
reword 499824e Adicionando nova feature2 versao 2

## Depois salve a saia!

## Um novo prompt será aberto e nele podemos fazer as mudanças
## que desejarmos na mensagem do(s) commit(s).


# Reveja os logs novamente:
$› git log
commit bcad00601db80e14ab5d74d161e1830721057f9b (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:33:04 2022 -0300

Nova versao para feature 2 para corrigir o bug 273-4

commit 92638015d0af92d5abd584ad06b625a0e6a5f6e2
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:56 2022 -0300

Nova versao para a feature 1 - v2

commit 80a1b8614070bf6b1073ea6865fb741b33877502
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:47 2022 -0300

Adicionando nova features versao 2


Fazendo rebase com a opção squash


#### O arquivo ainda não foi enviado para o servidor remoto!

# Veja os logs:
$› git log
commit bcad00601db80e14ab5d74d161e1830721057f9b (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:33:04 2022 -0300

Nova versao para feature 2 para corrigir o bug 273-4

commit 92638015d0af92d5abd584ad06b625a0e6a5f6e2
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:56 2022 -0300

Nova versao para a feature 1 - v2

commit 80a1b8614070bf6b1073ea6865fb741b33877502
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:47 2022 -0300

Adicionando nova features versao 2


## Agora vamos juntar os 3 commits dentro do último commit:
$› git rebase -i

## Agora mude de 'pick' para 'squash' para
## mudar apenas a mensagem do commit, você não deve mudar o primeiro commit,
## se quiser mudar ele use --amend e não rebase, vejamos o nosso exemplo abaixo:

pick 80a1b86 Adicionando nova features versao 2
squash 9263801 Nova versao para a feature 1 - v2
squash bcad006 Nova versao para feature 2 para corrigir o bug 273-4

## Depois salve a saia!

## Um novo prompt será aberto e nele podemos fazer as mudanças
## que desejarmos na mensagem do(s) commit(s). Você pode simplesmente manter
## as mensagens já existentes dentro do commit, mudar elas ou remover e deixar
## uma única mensagem (vou manter).

## Depois salve a saia!


# Veja os logs e note que estão em apenas um commit:
$› git log
commit a94d6d94c4fa3cb369eec6f54d4bd9233a1c24dd (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:47 2022 -0300

Adicionando nova features versao 2

Nova versao para a feature 1 - v2

Nova versao para feature 2 para corrigir o bug 273-4

# Outra forma de ver que está tudo dentro do mesmo commit:
$› git show --name-only -r HEAD
commit a94d6d94c4fa3cb369eec6f54d4bd9233a1c24dd (HEAD -> main)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 13:32:47 2022 -0300

Adicionando nova features versao 2

Nova versao para a feature 1 - v2

Nova versao para feature 2 para corrigir o bug 273-4

feature1/teste_v2
feature2/teste_v2
features/teste_v2


Recuperar um arquivo apagado


Vamos ver como recuperar um arquivo que foi apagado e foi commitado no repositório remoto, e vamos fazer isso sem influenciar no Branch main.

# Veja os logs:
$› git log -p -- teste | grep commit
commit f34d4c2905d68f32ad21bb39d0b9ed714b4dde66
commit 25fbc9c373216ec40abfea83b30c5d1dd2a4a427
commit 9c1d04c0c9710e85c9e5e7520631f38439480545
commit 134a961ffb5aa70313cc48159580ccd80d88ced7

## Normalmente o arquivo mais em cima é o último commit (delete no nosso caso),
## podemos conferir usando o comando abaixo:
$› git show --name-only -r f34d4c2905d68f32ad21bb39d0b9ed714b4dde66
commit f34d4c2905d68f32ad21bb39d0b9ed714b4dde66 (HEAD -> main, origin/main, origin/HEAD)
Author: FULANO <FULANO@exemplo.br>
Date: Tue Oct 4 16:16:01 2022 -0300

Removendo arquivo teste - Receita de bolo

teste

## Então selecione o abaixo dele '25fbc9c' e crie uma branch usando esse commit:

Agora vamos pegar 1 commit antes do que queremos, não adianta pegar o commit que apagamos o arquivo, e vamos criar uma nova branch usando esse commit:

# Crie uma branch usando o commit escolhido:
$› git checkout -b recover 25fbc9c
Switched to a new branch 'recover'

Pronto, o arquivo está disponível novamente!

# Veja usando o LS:
$› ls
feature1/ feature2/ features/ teste

# Veja usando o git:
$› git ls-files
feature1/teste_v1
feature1/teste_v2
feature2/teste_v1
feature2/teste_v2
features/teste_v1
features/teste_v2
teste

Quero incluir esse arquivo na branch main a partir da branch recover e agora? Primeiro vamos fazer o jeito certo, migrar o arquivo e todo o seu histórico para a branch main.

# Comece mudando para a branch main:
$› git checkout main

# Verifique os arquivos nessa branch:
$ git ls-files
feature1/teste_v1
feature1/teste_v2
feature2/teste_v1
feature2/teste_v2
features/teste_v1
features/teste_v2

# Agora faça o restore do arquivo desejado que está na branch 'recover':
$› git restore --source recover teste

# Verifique o status:
$› git status
No ramo main
Your branch is up to date with 'origin/main'.

Arquivos não monitorados:
(utilize "git add <arquivo>..." para incluir o que será submetido)
teste

nada adicionado ao envio mas arquivos não registrados estão presentes (use "git add" to registrar)

# Delete a branch 'recover':
$› git branch -d recover
Deleted branch recover (was a94d6d9).

# Faça o add, commit e depois push:
$› git add teste
$› git commit -m "Recuperando o arquivo de receita"
[main e9c935a] Recuperando o arquivo de receita
1 file changed, 19 insertions(+)
create mode 100644 teste
$› git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 4 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 677 bytes | 135.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To gitlab.com:FULANO/learngit.git
f34d4c2..e9c935a main -> main


# Verifique todos os commits para nos certificarmos de que migramos o
# historico também:
$› git log -p -- teste | grep commit
commit e9c935a1e8ece9a41368889a5ef7e093a529cfe9
commit f34d4c2905d68f32ad21bb39d0b9ed714b4dde66
commit 25fbc9c373216ec40abfea83b30c5d1dd2a4a427
commit 9c1d04c0c9710e85c9e5e7520631f38439480545
commit 134a961ffb5aa70313cc48159580ccd80d88ced7

Pronto, agora é só fazer o push para o arquivo como se fosse um novo arquivo.



Sincronizando uma branch com fetch


Você tem uma branch que está no repo remoto e ainda não está locamente e quer ela localmente, para isso faça:

# Sincronize a branch (baixar ela para o repo local):
$› git fetch origin branch_teste
From gitlab.com:FULANO/learngit
* branch branch_teste -> FETCH_HEA

# Mude para a branch:
$› git checkout branch_teste
Branch 'branch_teste' set up to track remote branch 'branch_teste' from 'origin'.
Switched to a new branch 'branch_teste'


Verificando de qual branch pertence um commit


Vamos ver de qual branch um commit pertence usando o parâmetro name-rev.

$ git name-rev 56aa2fa
56aa2fa master

$ git name-rev 0faac7e
0faac7e mudar_versao


Fazendo push para outra branch com Merge Request


Vamos fazer o push para uma outra branch que não seja a principal e durante o push já abrimos uma MR (Merge request) para ganhar tempo:

# Crie/Mude para a nova branch:
$› git checkout -b fix_teste

### Altere o arquivo(s)!

# Adicione o arquivo ao INDEX:
$› git add teste

## Faça o commit:
$› git commit -m "removendo linha final de teste"
[fix_teste 3c35898] removendo linha final de teste
1 file changed, 2 deletions(-)

# Faça o push para a branch desejada já com a solicitação do MR (merge request),
# o '-u origin branch_name' é necessário pois a branch ainda não existe no repositório remoto:
$› git push -u origin "fix_teste" -o merge_request.create
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 468 bytes | 468.00 KiB/s, done.
Total 4 (delta 2), reused 0 (delta 0)
remote:
remote: View merge request for fix_teste:
remote: https://gitlab.com/FULANO/learngit/-/merge_requests/1
remote:
To gitlab.com:FULANO/learngit.git
* [new branch] fix_teste -> fix_teste
Branch 'fix_teste' set up to track remote branch 'fix_teste' from 'origin'.


Merge de branch com Rebase - Sem conflito


O que vamos fazer é abrir um pedido de merge request para um branch e entao atualizar a branch main para que ela esteja a frente da branch que vamos mesclar, vou fazer de uma forma que não exista conflito:

#### Faça alguns commits na branch!

# Primeiro certifique-se de que a branch está atualizada:
$ git pull
Already up to date.

# Agora dentro da branch que vamos mergear, faça:
$› git rebase main
First, rewinding head to replay your work on top of it...
Applying: novos arquivos para nova feature

## Faça o pull para fazer o merge entre a branch remota e a local:
$› git pull

# Faça o push para enviar as mudanças:
$› git push

# Mude para a branch main:
$› git checkout main

# Faça o pull para atualizar a branch main:
$› git pull

# Remova a branch fix_teste:
$› git branch -d fix_teste
Deleted branch fix_teste (was 68806ba).

Agora está pronto para ser mesclado!



Merge com rebase - lidando com conflito


Vamos fazer um merge, mas antes disso vamos fazer um rebase para nos certificarmos que não vamos ter conflito durante o merge (vamos resolver o conflito durante o rebase). Podemos fazer isso com o merge sem rebase (acho melhor, mas pode ser que seja necessário suprimir os logs) e com o uso do rebase.

# Entre na branch feature1:
$ git checkout feature1

# Faça o rebase da branch com a main:
$ git rebase main
First, rewinding head to replay your work on top of it...
Applying: incrementado versao em 1 (final 52) na feature 1
Using index info to reconstruct a base tree...
M version
Falling back to patching base and 3-way merge...
Auto-merging version
CONFLICT (content): Merge conflict in version
error: Failed to merge in the changes.
Patch failed at 0001 incrementado versao em 1 (final 52) na feature 1
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

# Veja quem conflitou:
$ git diff --name-only --diff-filter=U
version

# Rode um status para ver como esta:
$ git status
rebase in progress; onto 1a08ea2
You are currently rebasing branch 'feature1' on '1a08ea2'.
(fix conflicts and then run "git rebase --continue")
(use "git rebase --skip" to skip this patch)
(use "git rebase --abort" to check out the original branch)

Unmerged paths:
(use "git restore --staged <file>..." to unstage)
(use "git add <file>..." to mark resolution)
both modified: version

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

#######################################################################
### A partir daqui vamos manter o version da feature1 igual o da main #
#######################################################################

# O arquivo ficou assim:
$ cat version
202865315953

# Edite o arquivo e resolva o conflito, depois faça:
$ git add version

# Faça um git status para ver se mudou o status:
$ git status
rebase in progress; onto 1a08ea2
You are currently rebasing branch 'feature1' on '1a08ea2'.
(all conflicts fixed: run "git rebase --continue")

nothing to commit, working tree clean


# Com os conflitos resolvidos e o arquivo adicionado faça:
$ git rebase --skip
Applying: novas features

## Com todos os conflitos resolvidos podemos fazer o merge sem dor de cabeça!

# Mude para a branch main:
$ git checkout main
Switched to branch 'main'

# Faça o merge local ou faça via browser:
$ git merge --no-ff feature1 -m "Merge feature1 into main"
Merge made by the 'recursive' strategy.
feature1 | 1 +
feature2 | 1 +
2 files changed, 2 insertions(+)
create mode 100644 feature1
create mode 100644 feature2


# Veja nos logs o merge:
$ git log -n 2 --oneline --decorate
57ce7d3 (HEAD -> main) Merge feature1 into main
7b1b131 (feature1) novas features

# Faça o push para o repositório remoto:
$ git push

# Depois remova a branch feature1 do repo remoto caso não vá mais usar:
$ git push origin :feature1

# Remova localmente:
$ git branch -d feature1


#######################################################################
### A partir daqui vamos manter o version da feature1 diferente ###
### do que temos main. ###
#######################################################################

# O arquivo ficou assim:
$ cat version
202865315954

# Edite o arquivo e resolva o conflito, depois faça:
$ git add version

# Faça um git status para ver se mudou o status:
$ git status
rebase in progress; onto 1a08ea2
You are currently rebasing branch 'feature1' on '1a08ea2'.
(all conflicts fixed: run "git rebase --continue")

Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: version


# Com os conflitos resolvidos e o arquivo adicionado faça:
$ git rebase --continue
Applying: incrementado versao em 1 (final 52) na feature 1
Applying: novas features

## Com todos os conflitos resolvidos podemos fazer o merge sem dor de cabeça!

# Mude para a branch main:
$ git checkout main
Switched to branch 'main'

# Faça o merge local ou faça via browser:
$ git merge --no-ff feature1 -m "Merge feature1 into main"
Merge made by the 'recursive' strategy.
feature1 | 1 +
feature2 | 1 +
version | 2 +-
3 files changed, 3 insertions(+), 1 deletion(-)
create mode 100644 feature1
create mode 100644 feature2

# Veja nos logs o merge:
$ git log -n 2 --oneline --decorate
3f20c69 (HEAD -> main) Merge feature1 into main
f4df843 (feature1) novas features

# Faça o push para o repositório remoto:
$ git push

# Depois remova a branch feature1 do repo remoto caso não vá mais usar:
$ git push origin :feature1

# Remova localmente:
$ git branch -d feature1

Quando temos conflito e deixamos os arquivos são iguais de ambas as branchs que estamos fazendo o rebase é como se não tivéssemos nenhum conflito, portando nós podemos usar o --skip para pular aquele patch em questão (já que mantivemos igual e isso anula o conflito).


Mas quando mudamos (deixando diferente de ambas as branchs) temos que dar o --continue sinalizando que vamos aplicar um novo valor para resolver o conflito e passar para outro patch, caso não tenha nenhum outro conflito é como se tivéssemos resolvido todos os conflitos.



Merge entre branchs - Sem Rebase


Vamos aplicar o merge entre Branchs sem usar o rebase, o merge vai ser realizado localmente. Primeiro vamos obter todos os arquivos da branch main dentro da nossa nova branch para que ambas fiquem no ponto certo para conseguir mesclar as duas sem nenhum problema, depois fazemos o push da branch local para a remota e por fim fazemos o merge.


Outro detalhe é que vamos manter todo o histórico da branch ao mergear ela. Primeiro começamos na branch main:

# Primeiro certifique-se de que a branch está atualizada:
$ git pull
Already up to date.


# Vou criar um arquivo de versão na branch main:
$ cat version
1.05

# Vou commit e criar uma branch baseada no ultimo commit da main:
$ git add version

$ git commit -m "Controle de versão"
[main 94b6eae] Controle de versão
1 file changed, 1 insertion(+)
create mode 100644 version

$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 284 bytes | 284.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To gitlab.com:FULANO/learngit.git
8bcde87..94b6eae main -> main


# Agora crie a branch:
$ git checkout -b new_version

Agora na branch new_version (chamada new_version) vamos alterar o arquivo de versão e fazer o push da nossa branch local para o repositório remoto.

# Altere a versão:
$ cat version
1.06

# Faça o commit e o push:
$ git add version

# Faça o commit:
$ git commit -m "Nova versao em branch new_version (versao 1.06)"
[new_version edd378d] Nova versao em branch new_version (versao 1.06)
1 file changed, 1 insertion(+), 1 deletion(-)

# Renomeie o arquivo 'pudim_receita':
$ git mv pudim_receita pudim

# Faça o push:
$ git push -u origin new_version
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 286 bytes | 286.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote:
remote: To create a merge request for new_version, visit:
remote: https://gitlab.com/FULANO/learngit/-/merge_requests/new?merge_request%5Bsource_branch%5D=new_version
remote:
To gitlab.com:FULANO/learngit.git
* [new branch] new_version -> new_version
Branch 'new_version' set up to track remote branch 'new_version' from 'origin'.

Volte para a branch main, vamos mudar novamente o arquivo de versão para criar um conflito, além disso, vamos adicionar mais arquivos.

# Mude para a branch main:
$ git checkout main

# Altere a versão:
$ cat version
1.07

# Faça o commit e o push:
$ git add version

$ git commit -m "Nova versão. Nova receita de como fazer pudim"
[main caab27d] Nova versão. Nova receita de como fazer pudim
2 files changed, 1 insertion(+), 1 deletion(-)
rename pudim_receita => pudim (100%)

# Faça o push agora:
$ git push
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 1.16 KiB | 1.16 MiB/s, done.
Total 4 (delta 1), reused 0 (delta 0)
To gitlab.com:FULANO/learngit.git
94b6eae..e829a74 main -> main

Ainda na branch main, vamos fazer o merge da branch new_version com a main.

# Faça o merge:
$ git merge new_version -m "Merge new_version into main"
Auto-merging version
CONFLICT (content): Merge conflict in version
Automatic merge failed; fix conflicts and then commit the result.

# Apesar do erro, o que poderia ser mesclado já foi.

Isso mostra que tem algum conflito, ele nos diz exatamente onde está o conflito CONFLICT (content): Merge conflict in version (no caso o nome do arquivo é version).


Agora vamos resolver o conflito:

# É possível obter os arquivos em conflito com o comando:
$ git diff --name-only --diff-filter=U
version

# Veja os arquivos que podemos editar:
$ git status
On branch main
Your branch is up to date with 'origin/main'.

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

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

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


# Veja uma diff do arquivo que está em conflito:
$ git diff version
diff --cc version
index 16e5283,d510f05..0000000
--- a/version
+++ b/version
@@@ -1,1 -1,1 +1,7 @@@
++<<<<<<< HEAD
+1.07
++||||||| 94b6eae
++1.05
++=======
+ 1.06
++>>>>>>> new_version

Vamos ver uma breve explicação sobre algumas novas linhas que podemos observar: <<<<<<< HEAD, ======= e >>>>>>>.

  • =======

    É a linha central do conflito.

  • <<<<<<< HEAD

    Todo conteúdo entre a linha central e a tag acima só existe na branch main atual no qual HEAD está apontando.

  • >>>>>>>

    Aqui é ao contrário, entre a linha cental e a tag acima temos um conteúdo que só existe na nossa branch que queremos fazer o merge.



Agora vamos resolver o conflito, o arquivo deve ficar assim:

$ cat version
1.07


### Para resolver o conflito edite o arquivo e deixe do jeito que deve ficar (por exemplo como deixei acima),
### Como você acha que o arquivo deva ser normalmente!

# Adicione o arquivo:
$ git add version

# Faça o commit:
$ git commit -m 'Corrigindo conflitos em version para o merge'
[changes fe82c6d] Corrigindo conflitos em teste

# Veja que está ok:
$ git pull
Already up to date.

# Faça o push e depois o merge (para a branch em questão):
$ git push
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 234 bytes | 234.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To gitlab.com:BRVN01/learngit.git
e829a74..cfaf203 main -> main

Ao fazer o push estamos mandando as branchs mescladas localmente para o repositório remoto. Sempre use o recurso de merge request para mesclar branchs.



Merge entre branchs com merge request


Vamos aplicar o merge entre Branchs sem usar o rebase, o merge vai ser realizado remotamente. Primeiro vamos obter todos os arquivos da branch main dentro da nossa nova branch para que ambas fiquem no ponto certo para conseguir mesclar as duas sem nenhum problema, depois fazemos o push da branch local para a remota e por fim fazemos o merge.


Outro detalhe é que vamos manter todo o histórico da branch ao mergear ela. Primeiro começamos na branch main:

# Primeiro certifique-se de que a branch está atualizada:
$ git pull
Already up to date.


# Vou criar um arquivo de versão na branch main:
$ cat version
1.08

# Vou commit e criar uma branch baseada no ultimo commit da main:
$ git add version

$ git commit -m "Controle de versão 1.8"
[main bfc0b79] Controle de versão 1.8
1 file changed, 1 insertion(+), 1 deletion(-)

$ git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 284 bytes | 284.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To gitlab.com:FULANO/learngit.git
8bcde87..94b6eae main -> main


# Agora crie a branch:
$ git checkout -b new_version-1.09

Agora na branch new_version (chamada new_version) vamos alterar o arquivo de versão e fazer o push da nossa branch local para o repositório remoto.

# Altere a versão:
$ cat version
1.09

# Faça o commit e o push:
$ git add version

# Faça o commit:
$ git commit -m "Nova versao em branch new_version (versao 1.09)"
[new_version-1.09 aa413e3] Nova versao em branch new_version (versao 1.09)
1 file changed, 1 insertion(+), 1 deletion(-)

# Faça o push:
$ git push -u origin new_version-1.09
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 285 bytes | 285.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote:
remote: To create a merge request for new_version-1.09, visit:
remote: https://gitlab.com/FULANO/learngit/-/merge_requests/new?merge_request%5Bsource_branch%5D=new_version-1.09
remote:
To gitlab.com:FULANO/learngit.git
* [new branch] new_version-1.09 -> new_version-1.09
Branch 'new_version-1.09' set up to track remote branch 'new_version-1.09' from 'origin'.

Volte para a branch main, vamos fazer o merge request.

# Faça a solicitação de merge de new_version-1.09 para a branch main:
$ git merge origin/new_version-1.09 -m "Merge new_version-1.09 into main"
Updating bfc0b79..aa413e3
Fast-forward (no commit created; -m option ignored)
version | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)


# Agora envie o pedido de merge para o repositório remoto:
$ git push
Total 0 (delta 0), reused 0 (delta 0)
To gitlab.com:BRVN01/learngit.git
bfc0b79..aa413e3 main -> main

# Pronto o merge foi realizado.

Ainda na branch main, vamos fazer o merge da branch new_version com a main.

# Faça o merge:
$ git merge new_version -m "Merge new_version into main"
Auto-merging version
CONFLICT (content): Merge conflict in version
Automatic merge failed; fix conflicts and then commit the result.

# Apesar do erro, o que poderia ser mesclado já foi.

Isso mostra que tem algum conflito, ele nos diz exatamente onde está o conflito CONFLICT (content): Merge conflict in version (no caso o nome do arquivo é version).


Agora vamos resolver o conflito:

# É possível obter os arquivos em conflito com o comando:
$ git diff --name-only --diff-filter=U
version

# Veja os arquivos que podemos editar:
$ git status
On branch main
Your branch is up to date with 'origin/main'.

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

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

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


# Veja uma diff do arquivo que está em conflito:
$ git diff version
diff --cc version
index 16e5283,d510f05..0000000
--- a/version
+++ b/version
@@@ -1,1 -1,1 +1,7 @@@
++<<<<<<< HEAD
+1.07
++||||||| 94b6eae
++1.05
++=======
+ 1.06
++>>>>>>> new_version

Vamos ver uma breve explicação sobre algumas novas linhas que podemos observar: <<<<<<< HEAD, ======= e >>>>>>>.

  • =======

    É a linha central do conflito.

  • <<<<<<< HEAD

    Todo conteúdo entre a linha central e a tag acima só existe na branch main atual no qual HEAD está apontando.

  • >>>>>>>

    Aqui é ao contrário, entre a linha cental e a tag acima temos um conteúdo que só existe na nossa branch que queremos fazer o merge.



Agora vamos resolver o conflito, o arquivo deve ficar assim:

$ cat version
1.07


### Para resolver o conflito edite o arquivo e deixe do jeito que deve ficar (por exemplo como deixei acima),
### Como você acha que o arquivo deva ser normalmente!

# Adicione o arquivo:
$ git add version

# Faça o commit:
$ git commit -m 'Corrigindo conflitos em version para o merge'
[changes fe82c6d] Corrigindo conflitos em teste

# Veja que está ok:
$ git pull
Already up to date.

# Faça o push e depois o merge (para a branch em questão):
$ git push
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 234 bytes | 234.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To gitlab.com:BRVN01/learngit.git
e829a74..cfaf203 main -> main

Ao fazer o push estamos mandando as branchs mescladas localmente para o repositório remoto.



Resolver conflitos antes do merge


Aqui vamos primeiramente resolver conflitos antes de aplicar o merge, é como antecipar um conflito que aconteceria se não fizéssemos nada, na prática vamos alterar todos os conteúdos que iriam dar conflito, dai vamos comitar e quando formos mesclar não vamos ter nenhum erro.



Resolver conflitos locais e remotos


Primeiro vamos começar com uma resolução de conflitos sem conflitos, esse é o cenário que todos queremos sempre.

# Comece aplicando um 'pull':
$ git pull
Already up to date.

# Obtenha o ultimo commit feito nessa branch:
$ git log --oneline --decorate | grep teste_branch
11a9ce6e (HEAD -> teste_branch, origin/teste_branch) Testes de conflito sem merge

# Agora faça o merge:
$ git merge master -m "Merging test. Merge master into teste_branch"
Mesclagem automática de XX/db.test
Merge made by the 'recursive' strategy.
XX/db.test | 1 -
1 files changed, 1 deletions(-)

# Vamos apagar as modificações realizadas localmente para não enviar para
# o repositório remoto:
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

# Delete a branch:
$ git branch -D teste_branch
Deleted branch teste_branch (was c65ec1b0).

Agora vamos ver como resolver caso tenha conflito, esse é o cenário que não queremos, aqui é tudo muito simples, mas num projeto real podem ser tantos conflitos, e cada conflito mais complicado do que o anterior.

# Comece aplicando um 'pull':
$ git pull
Already up to date.

# Obtenha o ultimo commit feito nessa branch:
$ git log --oneline --decorate | grep teste_branch
6610587 (HEAD -> feature1, origin/feature1) add versao = 2 em feature1
3ed6f85 Add feature em feature1

# Agora faça o merge:
$ git merge master -m "Merging test. Merge master into feature1"
Auto-merging versao
CONFLICT (content): Merge conflict in versao
Automatic merge failed; fix conflicts and then commit the result.


# É possível obter os arquivos em conflito com o comando:
$ git diff --name-only --diff-filter=U
versao

# Sabendo que esse arquivo está em conflito vamos
# fazer um rollback do repo local e sanar o conflito,
# use o hash do último commit, obtido acima:
$ git reset --hard 6610587
HEAD is now at 6610587 add versao = 2 em feature1

# Edite o arquivo versão para sanar o conflito, meu arquivo ficou
# igual ao arquivo na branch master:
$ cat versao
4

# Adicione, faça o commit e depois o push para o repo remoto:
$ git add versao

$ git commit -m "Sanando conflito para merge request"
[feature1 3dafaf5] Sanando conflito para merge request
1 file changed, 1 insertion(+), 1 deletion(-)

$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 273 bytes | 273.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To file:///opt/git_repos/myrepo.git
6610587..3dafaf5 feature1 -> feature1

### Pronto, a branch pode ser mesclada sem nenhum problema!

# Vamos apagar as modificações realizadas localmente para não enviar para
# o repositório remoto:
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.

# Delete a branch:
$ git branch -D teste_branch
Deleted branch teste_branch (was c65ec1b0).

Como não deu erro nós podemos mesclar sem nenhum problema.



Conflito de versões - Remota versus Local


Pode ocorrer de quando você executar git pull o Git detectar que existem alterações no repositório Local e também haver alterações no repositório Remoto, no entanto, as alterações no repositório local não foram comitadas e por causa disso, as alterações Locais vão conflitar com as alterações remotas.


Segue um exemplo desse problema:

$ git pull
Updating 884cd9a..917f8d7
error: Your local changes to the following files would be overwritten by merge:
file1.txt
file2.txt
Please commit your changes or stash them before you merge.
Aborting

Existem algumas formas de resolver esse pequeno inconveniente.



Commitar as alterações locais


Se suas alterações locais estão corretas e deseja mantê-las, faça um commit antes do pull:

# Adicione todos os arquivos modificados ao stage:
$ git add .

# Commite com as alterações:
$ git commit -m "Mensagem do commit"

# Agora pode fazer o pull para baixar as novas alterações:
$ git pull


Salvar as alterações temporariamente usando Stash


Vamos usar o git stash para armazenar temporariamente suas alterações em um estado de stash, permitindo que possamos fizar a mesclagem. Para mais detalhes do stash veja aqui.

# Execute o stash para salvar as alterações locais:
$ git stash
Saved working directory and index state WIP on main: 884cd9a Improving description.

# Execute o 'pull':
$ git pull
Updating 884cd9a..917f8d7
Fast-forward
file1.txt | 2 +-
file2.txt | 2 +-
file3.txt | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)

# Execute o stash novamente para recuperar as alterações que tinhamos feito:
$ git stash pop
Auto-merging file1.txt
Auto-merging file2.txt
On branch main

Agora é só executar o add, commit e push.



Fontes


https://docs.gitlab.com/ee/development/integrations/secure.html#

https://docs.gitlab.com/ee/ci/yaml/index.html#image

https://www.youtube.com/watch?v=6OokP-NE49k

https://www.youtube.com/watch?v=M4h5nieYBX