Na primeira parte aprendemos a fazer o controle de versões de um projeto localmente: as áreas do git, a configuração inicial e o fluxo de commits. Neste segundo capítulo, vamos nos aprofundar nas **branches**: como criá-las, mover-se entre elas, mesclá-las e resolver conflitos. 🎸
Aviso: Este post foi traduzido para o português usando um modelo de tradução automática. Por favor, me avise se encontrar algum erro.
📚 **Esta entrada faz parte da série _Guia de Git_**, dividida em três capítulos que se leem em ordem:
> * Parte 1: Controle de versões em local
* 👉 **Parte 2: Ramos**
* Parte 3: Repositórios remotos, stash e tags
Ramos
O uso de branches é muito útil, já que podemos começar a desenvolver uma nova funcionalidade sem ter que modificar o código original
Criar uma branch (git branch <branch name>)
**Nota**: Antes de tudo, é preciso dizer que, para criar uma branch em um repositório, deve haver pelo menos um commit; se tentar criar uma branch antes de fazer o primeiro commit, receberemos um erro
Para criar uma ramificação utilizamos o comando git branch <nombre de la rama>
InputPython!cd notebook_git && git branch new_branchCopied
Listar ramificações (git branch)
Criámos a nossa primeira branch; podemos verificar todas as branches que temos criadas escrevendo apenas git branch
InputPython!cd notebook_git && git branchCopied
* masternew_branch
Além de listar, ele nos diz com um asterisco * em qual branch estamos, neste caso na branch master
Renomear branches, adeus à branch master (git branch -m <old name> <new name>)
Historicamente, no git a rama principal era chamada master, mas isso tem conotações históricas ruins por causa do conceito de master-slave (mestre-escravo), devido ao sofrimento que muitas pessoas sofreram, por isso agora costuma-se nomear a rama principal como main, então para mudar o nome usamos git branch -m master main
InputPython!cd notebook_git && git branch -m master mainCopied
Listamos os ramos
InputPython!cd notebook_git && git branchCopied
* mainnew_branch
Como vemos, conseguimos mudar o nome do branch principal de master para main
Mudar de branch (git switch <branch>)
Se quisermos mudar de branch, basta escrever git switch <nome da branch>
InputPython!cd notebook_git && git switch new_branchCopied
Cambiado a rama 'new_branch'
Vamos ver em que branch estamos com git branch
InputPython!cd notebook_git && git branchCopied
main* new_branch
Como vemos, mudamos para a branch new_branch
Se quisermos criar e mudar de branch em um único comando, podemos usar git switch -c <nome do branch>
InputPython!cd notebook_git && git switch -c new_branch2Copied
Cambiado a nueva rama 'new_branch2'
Vamos ver em que ramo estamos
InputPython!cd notebook_git && git branchCopied
mainnew_branch* new_branch2
Criamos e mudamos de branch com um único comando
Obter a branch em que estamos (git branch --show-current)
Como vimos até agora com git branch, podemos obter uma lista de todos os branches e também ver em qual estamos atualmente, mas no caso em que tenhamos uma grande quantidade de branches, o que pode acontecer em uma equipe de trabalho com muita gente, é bom obter o branch atual sem obter uma lista de todos; para isso usamos git branch --show-current
InputPython!cd notebook_git && git branch --show-currentCopied
new_branch2
Lista de branches mais recentes (git branch --sort=-committerdate)
No caso de ter muitos ramos, talvez nos interesse saber quais são os mais recentes para ver quais foram os últimos criados e onde deve estar o que há de mais recente em desenvolvimento. Para isso usamos git branch --sort=-committerdate
InputPython!cd notebook_git && git branch --sort=-committerdateCopied
* new_branch2new_branchmain
Como vemos, ele as ordenou em ordem inversa ao momento em que as criamos
O comando preterido git checkout
Até há algum tempo, o comando para criar branches e alternar entre elas era git checkout, mas esse comando não apenas faz isso, como também restaura o diretório de trabalho. Porém, isso vai contra a filosofia do Linux, por isso foram criados os comandos git branch, git switch e git restore para dividir essa funcionalidade
Mesclando branches (git merge)
Como dissemos, criar branches é muito útil para desenvolver novas funcionalidades sem afetar o restante da equipe. Mas, quando elas estão prontas, é preciso levá-las para a branch principal; para isso utilizamos o comando git merge <rama>
**Importante**: Temos que estar na rama que vai adotar as alterações, ou seja, se quisermos fundir as alterações realizadas na rama
new_branch2na ramamain, primeiro temos que nos assegurar de estar na ramamain
Primeiro, verificamos em que ramo estamos
InputPython!cd notebook_git && git branch --show-currentCopied
new_branch2
Eliminamos arquivo7.py
InputPython!cd notebook_git && git rm archivo7.pyCopied
rm 'archivo7.py'
Fazemos um commit com as mudanças
InputPython!cd notebook_git && git commit -am "Eliminado archivo7.py"Copied
[new_branch2 5168f78] Eliminado archivo7.py1 file changed, 1 deletion(-)delete mode 100644 archivo7.py
Se fizermos um ls, vemos que archivo7.py já não está
InputPython!cd notebook_git && ls | grep archivo7Copied
Criamos um novo arquivo e fazemos um commit
InputPython!cd notebook_git && touch archivo8.py && git add archivo8.py && git commit -m "Commit con el archivo 8"Copied
[new_branch2 564ccfb] Commit con el archivo 81 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 archivo8.py
Fizemos dois novos commits nesta branch, vamos vê-lo com git log
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 564ccfb (HEAD -> new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch, main) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Mudamos para a ramificação principal
InputPython!cd notebook_git && git switch mainCopied
Cambiado a rama 'main'
Se agora fizermos novamente ls, veremos que archivo7.py sim está presente
InputPython!cd notebook_git && ls | grep archivo7Copied
archivo7.py
Fundimos os ramos, trazemos as alterações de new_branch2 para main
InputPython!cd notebook_git && git merge new_branch2Copied
Actualizando 4bb9d75..564ccfbFast-forwardarchivo7.py | 1 -archivo8.py | 02 files changed, 1 deletion(-)delete mode 100644 archivo7.pycreate mode 100644 archivo8.py
Fazemos um git status
InputPython!cd notebook_git && git statusCopied
En la rama mainnada para hacer commit, el árbol de trabajo está limpio
Vemos que ao fazer o merge não é necessário fazer nenhum commit, vejamos com um git log o que aconteceu
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 564ccfb (HEAD -> main, new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Vemos que o commit da branch new_branch2 foi incorporado a esta branch
Avanço rápido
Neste caso, criamos uma nova branch, não tocamos na principal e apenas modificamos a nova, realizando vários commits. Portanto, ao unir a nova com a principal, todos os commits que foram feitos na nova serão vistos. Para realizar esse tipo de merge, escrevemos git merge --ff-only <rama>
InputPython### Este código es para crear el gráfico de las ramas, no es necesario para el cursoimport graphviz# Crear el gráfico con la dirección de las flechas de izquierda a derechaorin = graphviz.Digraph('G', graph_attr={'rankdir': 'LR'})fast_foward = graphviz.Digraph('G', graph_attr={'rankdir': 'LR'})# Agregar nodos (pelotas) A, B, C y D en la rama principalorin.node('A', shape='circle', label='A', color='blue')orin.node('B', shape='circle', label='B', color='blue')orin.node('C', shape='circle', label='C', color='blue')orin.node('D', shape='circle', label='D', color='blue')orin.node('E', shape='circle', label='', color='transparent')fast_foward.node('A', shape='circle', label='A', color='blue')fast_foward.node('B', shape='circle', label='B', color='blue')fast_foward.node('C', shape='circle', label='C', color='blue')fast_foward.node('D', shape='circle', label='D', color='blue')# Agregar nodos (pelotas) X e Y en la rama secundariaorin.node('X', shape='circle', label='X', color='green')orin.node('Y', shape='circle', label='Y', color='green')fast_foward.node('X', shape='circle', label='X', color='magenta')fast_foward.node('Y', shape='circle', label='Y', color='magenta')# Agregar flechas entre los nodos en la rama principalorin.edges(['AB', 'BC', 'CD'])orin.edge('D', 'E', color='transparent') # Hacer la flecha de C a D transparentefast_foward.edges(['AB', 'BC', 'CD', 'DX', 'XY'])# Agregar flechas entre los nodos en la rama secundariaorin.edges(['DX', 'XY'])# Mostrar el diagrama de flujo en la celda de código de Jupyter Notebookdisplay(orin)display(fast_foward)Copied
<graphviz.graphs.Digraph at 0x7f58f80c09a0>
<graphviz.graphs.Digraph at 0x7f58f9203fa0>
Vamos primeiro verificar se estamos na branch principal
InputPython!cd notebook_git && git branch --show-currentCopied
main
Criamos uma nova branch
InputPython!cd notebook_git && git branch branch_fast_forwardCopied
Mudamos para ela
InputPython!cd notebook_git && git switch branch_fast_forwardCopied
Cambiado a rama 'branch_fast_forward'
InputPython!cd notebook_git && git branch --show-currentCopied
branch_fast_forward
Vamos ver o log
InputPython!cd notebook_git && git log --graph --oneline --decorate --allCopied
* 564ccfb (HEAD -> branch_fast_forward, new_branch2, main) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Certo, estamos em um branch criado a partir do principal com todo o seu histórico de logs, fazemos dois novos commits
InputPython!cd notebook_git && git rm archivo4.py && git commit -am "Eliminado archivo4.py"Copied
rm 'archivo4.py'[branch_fast_forward 4484e70] Eliminado archivo4.py1 file changed, 1 deletion(-)delete mode 100644 archivo4.py
InputPython!cd notebook_git && git rm hola.py && git commit -am "Eliminado hola.py"Copied
rm 'hola.py'[branch_fast_forward 94149fc] Eliminado hola.py1 file changed, 3 deletions(-)delete mode 100644 hola.py
Fazemos um novo log para ver que, nesta nova branch, foram criados
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 94149fc (HEAD -> branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2, main) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Como vemos, os dois últimos commits são os que criamos e podemos verificar que esses commits não estão na branch principal (para isso, especifico que seja feito sobre a branch main)
InputPython!cd notebook_git && git log main --graph --oneline --decorateCopied
* 564ccfb (new_branch2, main) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Agora vamos para a branch main para fazer o merge
InputPython!cd notebook_git && git switch mainCopied
Cambiado a rama 'main'
Por fim, fazemos o merge do tipo fast forward
InputPython!cd notebook_git && git merge --ff-only branch_fast_forwardCopied
Actualizando 564ccfb..94149fcFast-forwardarchivo4.py | 1 -hola.py | 3 ---2 files changed, 4 deletions(-)delete mode 100644 archivo4.pydelete mode 100644 hola.py
O merge foi feito, vamos ver o que aconteceu com o log na branch main
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 94149fc (HEAD -> main, branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Como se vê, foram mantidos os dois commits feitos na rama branch_fast_forward
Sem fast-forward ou merge verdadeiro
Neste caso, criamos uma nova branch, não tocamos na principal e modificamos a nova, realizando vários commits. Em seguida, fazemos um commit na principal. Portanto, ao unir a nova na principal, será visto um único commit na nova. Para fazer esse tipo de merge, escrevemos git merge <rama> --no-ff
InputPython### Este código es para crear el gráfico de las ramas, no es necesario para el cursoimport graphviz# Crear el gráfico con la dirección de las flechas de izquierda a derechaorin = graphviz.Digraph('G', graph_attr={'rankdir': 'LR'})not_fast_forward = graphviz.Digraph('G', graph_attr={'rankdir': 'LR'})# Agregar nodos (pelotas) A, B, C y D en la rama principalorin.node('A', shape='circle', label='A', color='blue')orin.node('B', shape='circle', label='B', color='blue')orin.node('C', shape='circle', label='C', color='blue')orin.node('D', shape='circle', label='D', color='blue')orin.node('E', shape='circle', label='', color='transparent')not_fast_forward.node('A', shape='circle', label='A', color='blue')not_fast_forward.node('B', shape='circle', label='B', color='blue')not_fast_forward.node('C', shape='circle', label='C', color='blue')not_fast_forward.node('D', shape='circle', label='D', color='blue')not_fast_forward.node('E', shape='circle', label='E', color='blue')# Agregar nodos (pelotas) X e Y en la rama secundariaorin.node('X', shape='circle', label='X', color='green')orin.node('Y', shape='circle', label='Y', color='green')not_fast_forward.node('X', shape='circle', label='X', color='green')not_fast_forward.node('Y', shape='circle', label='Y', color='green')# Agregar nodo (pelota) M en la rama principalnot_fast_forward.node('M', shape='circle', label='M', color='magenta')# Agregar flechas entre los nodos en la rama principalorin.edges(['AB', 'BC', 'CD'])orin.edge('D', 'E', color='transparent') # Hacer la flecha de C a D transparentenot_fast_forward.edges(['AB', 'BC', 'CD', 'DE'])# Agregar flechas entre los nodos en la rama secundariaorin.edges(['DX', 'XY'])not_fast_forward.edges(['DX', 'XY', 'YM'])# Agregar flechas de la rama principal al nodo Mnot_fast_forward.edge('E', 'M')# Mostrar el diagrama de flujo en la celda de código de Jupyter Notebookdisplay(orin)display(not_fast_forward)Copied
<graphviz.graphs.Digraph at 0x7f58f80c2fb0>
<graphviz.graphs.Digraph at 0x7f58f80c2230>
Vamos primeiro verificar se estamos na ramificação principal
InputPython!cd notebook_git && git branch --show-currentCopied
main
Criamos uma nova branch
InputPython!cd notebook_git && git branch branch_no_fast_forwardCopied
Trocamos para ela
InputPython!cd notebook_git && git switch branch_no_fast_forwardCopied
Cambiado a rama 'branch_no_fast_forward'
InputPython!cd notebook_git && git branch --show-currentCopied
branch_no_fast_forward
Certo, estamos em uma branch criada a partir da principal com todo o seu histórico de logs, fazemos dois novos commits
InputPython!cd notebook_git && touch file1 && git add file1 && git commit -m "file1"Copied
[branch_no_fast_forward e4e23c9] file11 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 file1
InputPython!cd notebook_git && touch file2 && git add file2 && git commit -m "file2"Copied
[branch_no_fast_forward 8df3429] file21 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 file2
Fazemos um novo log para ver o que nesta nova ramificação foi criado
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 8df3429 (HEAD -> branch_no_fast_forward) file2* e4e23c9 file1* 94149fc (main, branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Como vemos, os dois últimos commits são os que criamos e podemos verificar que esses commits não estão na branch principal (para isso especifico que seja feito sobre a branch main)
InputPython!cd notebook_git && git log main --graph --oneline --decorateCopied
* 94149fc (main, branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Agora vamos para a branch main
InputPython!cd notebook_git && git switch mainCopied
Cambiado a rama 'main'
Criamos um novo commit
InputPython!cd notebook_git && touch file3 && git add file3 && git commit -m "file3"Copied
[main 8bdf4d8] file31 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 file3
Por último, fazemos o merge do tipo não fast forward
InputPython!cd notebook_git && git merge branch_no_fast_forward --no-ffCopied
ommit. comenzando con '#' serán ignoradas, y un mensaje vacío abortasaria esta># especialmente si esto fusiona un upstream actualizado en una rama de tópico. /home/wallabot/Documentos/web/portafolio/posts/notebook_git/.git/MERGE_MSG [ línea 1/7 (14%), col 1/48 (2%), car 0/301 (0%) ] [ Párrafo justificado ]...llabot/Documentos/web/portafolio/posts/notebook_git/.git/MERGE_MSG Modificado
Como vemos, abre o editor para introduzir uma mensagem de commit e uma mensagem por defeito. Aceitamos a mensagem e vemos o que aconteceu
InputPython!cd notebook_git && git statusCopied
En la rama mainnada para hacer commit, el árbol de trabajo está limpio
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 274529c (HEAD -> main) Merge branch 'branch_no_fast_forward' into main|\| * 8df3429 (branch_no_fast_forward) file2| * e4e23c9 file1* | 8bdf4d8 file3|/* 94149fc (branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
InputPython!cd notebook_git && lsCopied
api_keys.py archivo1.py archivo2.py archivo8.py file1 file2 file3
Como vemos, foi criado um novo commit com as alterações da nova branch na branch principal
Esmagamento
Nesse tipo de fusão, todos os commits de uma nova branch são reunidos em um único commit na branch principal; para isso, escrevemos git merge <rama> --squash
InputPython### Este código es para crear el gráfico de las ramas, no es necesario para el cursoimport graphviz# Crear el gráfico con la dirección de las flechas de izquierda a derechaorin = graphviz.Digraph('G', graph_attr={'rankdir': 'LR'})squash = graphviz.Digraph('G', graph_attr={'rankdir': 'LR'})# Agregar nodos (pelotas) A, B, C y D en la rama principalorin.node('A', shape='circle', label='A', color='blue')orin.node('B', shape='circle', label='B', color='blue')orin.node('C', shape='circle', label='C', color='blue')orin.node('D', shape='circle', label='D', color='blue')orin.node('E', shape='circle', label='', color='transparent')squash.node('A', shape='circle', label='A', color='blue')squash.node('B', shape='circle', label='B', color='blue')squash.node('C', shape='circle', label='C', color='blue')squash.node('D', shape='circle', label='D', color='blue')# Agregar nodos (pelotas) X e Y en la rama secundariaorin.node('X', shape='circle', label='X', color='green')orin.node('Y', shape='circle', label='Y', color='green')# Agregar nodo (pelota) M en la rama principalsquash.node('M', shape='circle', label='M', color='magenta')# Agregar flechas entre los nodos en la rama principalorin.edges(['AB', 'BC', 'CD'])orin.edge('D', 'E', color='transparent') # Hacer la flecha de C a D transparentesquash.edges(['AB', 'BC', 'CD', 'DM'])# Agregar flechas entre los nodos en la rama secundariaorin.edges(['DX', 'XY'])# Mostrar el diagrama de flujo en la celda de código de Jupyter Notebookdisplay(orin)display(squash)Copied
<graphviz.graphs.Digraph at 0x7f58f80e6470>
<graphviz.graphs.Digraph at 0x7f58f80e6f80>
Vamos primeiro verificar se estamos na branch principal
InputPython!cd notebook_git && git branch --show-currentCopied
main
Criamos um novo branch
InputPython!cd notebook_git && git branch branch_squashCopied
Mudamos para ela
InputPython!cd notebook_git && git switch branch_squashCopied
Cambiado a rama 'branch_squash'
InputPython!cd notebook_git && git branch --show-currentCopied
branch_squash
Vamos ver o log
InputPython!cd notebook_git && git log --graph --oneline --decorate --allCopied
* 274529c (HEAD -> branch_squash, main) Merge branch 'branch_no_fast_forward' into main|\| * 8df3429 (branch_no_fast_forward) file2| * e4e23c9 file1* | 8bdf4d8 file3|/* 94149fc (branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Ok, estamos em uma ramificação criada a partir da principal com todo o seu histórico de logs, fazemos três novos commits
InputPython!cd notebook_git && git rm file1 && git commit -am "Eliminado file1"Copied
rm 'file1'[branch_squash 767b632] Eliminado file11 file changed, 0 insertions(+), 0 deletions(-)delete mode 100644 file1
InputPython!cd notebook_git && git rm file2 && git commit -am "Eliminado file2"Copied
rm 'file2'[branch_squash a47f771] Eliminado file21 file changed, 0 insertions(+), 0 deletions(-)delete mode 100644 file2
InputPython!cd notebook_git && git rm file3 && git commit -am "Eliminado file3"Copied
rm 'file3'[branch_squash 85f8c9f] Eliminado file31 file changed, 0 insertions(+), 0 deletions(-)delete mode 100644 file3
Fazemos um novo log para ver que nesta nova branch foram criados
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 85f8c9f (HEAD -> branch_squash) Eliminado file3* a47f771 Eliminado file2* 767b632 Eliminado file1* 274529c (main) Merge branch 'branch_no_fast_forward' into main|\| * 8df3429 (branch_no_fast_forward) file2| * e4e23c9 file1* | 8bdf4d8 file3|/* 94149fc (branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Como vemos, os três últimos commits são os que criamos e podemos comprovar que esses commits não estão na branch principal (para isso especifico que o faça sobre a branch main)
InputPython!cd notebook_git && git log main --graph --oneline --decorateCopied
* 274529c (main) Merge branch 'branch_no_fast_forward' into main|\| * 8df3429 (branch_no_fast_forward) file2| * e4e23c9 file1* | 8bdf4d8 file3|/* 94149fc (branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Agora vamos para a ramificação main para fazer o merge
InputPython!cd notebook_git && git switch mainCopied
Cambiado a rama 'main'
Fazemos o merge do tipo squash
InputPython!cd notebook_git && git merge branch_squash --squashCopied
Actualizando 274529c..85f8c9fFast-forwardCommit de aplastamiento -- no actualizando HEADfile1 | 0file2 | 0file3 | 03 files changed, 0 insertions(+), 0 deletions(-)delete mode 100644 file1delete mode 100644 file2delete mode 100644 file3
A mesclagem foi feita, vamos ver o que aconteceu com o log na branch main
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 274529c (HEAD -> main) Merge branch 'branch_no_fast_forward' into main|\| * 8df3429 (branch_no_fast_forward) file2| * e4e23c9 file1* | 8bdf4d8 file3|/* 94149fc (branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
As alterações feitas no branch não aparecem, vamos fazer um git status
InputPython!cd notebook_git && git statusCopied
En la rama mainCambios a ser confirmados:(usa "git restore --staged <archivo>..." para sacar del área de stage)borrados: file1borrados: file2borrados: file3
Vemos que temos que fazer o commit com a fusão. Isso é porque o Git não sabe que mensagem colocar e deixa para nós fazermos isso, de modo que o fazemos
InputPython!cd notebook_git && git commit -m "Merge squash de los commits de la rama branch_squash"Copied
[main 52acb97] Merge squash de los commits de la rama branch_squash3 files changed, 0 insertions(+), 0 deletions(-)delete mode 100644 file1delete mode 100644 file2delete mode 100644 file3
Vamos fazer novamente um git log
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 52acb97 (HEAD -> main) Merge squash de los commits de la rama branch_squash* 274529c Merge branch 'branch_no_fast_forward' into main|\| * 8df3429 (branch_no_fast_forward) file2| * e4e23c9 file1* | 8bdf4d8 file3|/* 94149fc (branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Conflitos ao mesclar
Quando ramificações são mescladas, pode acontecer de um mesmo arquivo ter sido modificado em várias ramificações. Isso pode ser normal em projetos em que várias pessoas estão desenvolvendo, então vamos ver como resolver isso.
Criamos um conflito
Verificamos que estamos na branch main
InputPython!cd notebook_git && git branch --show-currentCopied
main
Criamos um novo branch a partir desta
InputPython!cd notebook_git && git branch rama_con_conflictoCopied
Adicionamos uma linha ao arquivo archivo1.py, lembramos que estamos na branch main
InputPython!cd notebook_git && echo "print('rama main')" >> archivo1.pyCopied
InputPython!cd notebook_git && cat archivo1.pyCopied
print('Este es el archivo 1')print('rama main')
arquivo1.py está modificado, fazemos um commit
InputPython!cd notebook_git && git add archivo1.py && git commit -m "archivo1.py en rama main"Copied
[main 53f909b] archivo1.py en rama main1 file changed, 1 insertion(+)
Agora vamos para a branch rama_con_conflicto e adicionamos uma nova linha a archivo1.py
InputPython!cd notebook_git && git switch rama_con_conflictoCopied
Cambiado a rama 'rama_con_conflicto'
InputPython!cd notebook_git && git branch --show-currentCopied
rama_con_conflicto
InputPython!cd notebook_git && echo "print('rama rama_con_conflicto')" >> archivo1.pyCopied
InputPython!cd notebook_git && cat archivo1.pyCopied
print('Este es el archivo 1')print('rama rama_con_conflicto')
Como vemos, arquivo1.py não é igual na rama main e na rama rama_con_conflicto. Fazemos um commit com a modificação de arquivo1.py na rama rama_con_conflicto
InputPython!cd notebook_git && git add archivo1.py && git commit -m "archivo1.py en rama rama_con_conflicto"Copied
[rama_con_conflicto 32851c3] archivo1.py en rama rama_con_conflicto1 file changed, 1 insertion(+)
Voltamos para a branch main
InputPython!cd notebook_git && git switch mainCopied
Cambiado a rama 'main'
InputPython!cd notebook_git && git branch --show-currentCopied
main
Fazemos um merge da rama rama_con_conflicto
InputPython!cd notebook_git && git merge rama_con_conflictoCopied
Auto-fusionando archivo1.pyCONFLICTO (contenido): Conflicto de fusión en archivo1.pyFusión automática falló; arregle los conflictos y luego realice un commit con el resultado.
Ao fazer o merge, ele já nos avisa que há um conflito em archivo1.py e que não foi possível fazer o merge. Fazemos um git status
InputPython!cd notebook_git && git statusCopied
En la rama mainTienes rutas no fusionadas.(arregla los conflictos y ejecuta "git commit"(usa "git merge --abort" para abortar la fusion)Rutas no fusionadas:(usa "git add <archivo>..." para marcar una resolución)modificados por ambos: archivo1.pysin cambios agregados al commit (usa "git add" y/o "git commit -a")
Ele nos diz a mesma coisa, mas nos dá mais informações; nos diz que podemos abortar a fusão com git merge --abort. Mas, em vez disso, vamos resolvê-lo
Resolver um conflito
No nosso caso, sabemos onde está o problema, mas, caso não soubéssemos, por meio de git diff podemos encontrar o problema
InputPython!cd notebook_git && git diff archivo1.pyCopied
diff --cc archivo1.pyindex 8b4bf58,b5c003c..0000000--- a/archivo1.py+++ b/archivo1.py@@@ -1,2 -1,2 +1,6 @@@print('Este es el archivo 1')++<<<<<<< HEAD+print('rama main')++=======+ print('rama rama_con_conflicto')++>>>>>>> rama_con_conflicto
git diff está nos dizendo que o problema está na última linha. A versão do arquivo da branch HEAD (na qual estamos atualmente main) tem print('rama main') na última linha, enquanto a versão da branch rama_con_conflicto tem print('rama rama_con_conflicto') na última linha. Portanto, é preciso abrir o arquivo com qualquer editor e resolver isso.
Depois de editar o arquivo com meu editor de código, removi todas as linhas extras e ele ficou assim
InputPython!cd notebook_git && cat archivo1.pyCopied
print('Este es el archivo 1')print('rama main')
Agora fazemos um git status para ver o que temos que fazer
InputPython!cd notebook_git && git statusCopied
En la rama mainTienes rutas no fusionadas.(arregla los conflictos y ejecuta "git commit"(usa "git merge --abort" para abortar la fusion)Rutas no fusionadas:(usa "git add <archivo>..." para marcar una resolución)modificados por ambos: archivo1.pysin cambios agregados al commit (usa "git add" y/o "git commit -a")
Diz-nos que temos o arquivo archivo1.py com modificações, por isso o adicionamos à área de staged e depois fazemos um commit
InputPython!cd notebook_git && git add archivo1.py && git commit -m "archivo1.py con el merge resuelto"Copied
[main 679bb49] archivo1.py con el merge resuelto
Voltamos a fazer um git status para ver se foi resolvido
InputPython!cd notebook_git && git statusCopied
En la rama mainnada para hacer commit, el árbol de trabajo está limpio
Parece que foi resolvido, fazemos um git log para verificá-lo
InputPython!cd notebook_git && git log --graph --oneline --decorateCopied
* 679bb49 (HEAD -> main) archivo1.py con el merge resuelto|\| * 32851c3 (rama_con_conflicto) archivo1.py en rama rama_con_conflicto* | 53f909b archivo1.py en rama main|/* 52acb97 Merge squash de los commits de la rama branch_squash* 274529c Merge branch 'branch_no_fast_forward' into main|\| * 8df3429 (branch_no_fast_forward) file2| * e4e23c9 file1* | 8bdf4d8 file3|/* 94149fc (branch_fast_forward) Eliminado hola.py* 4484e70 Eliminado archivo4.py* 564ccfb (new_branch2) Commit con el archivo 8* 5168f78 Eliminado archivo7.py* 4bb9d75 (new_branch) Commit con el archivo 7* ea615a9 Eliminado archivo5.py* e3153a5 Commit con los archivos 4 y 5* 0b09cfa Añadido .gitignore* 04ebd1f Commit con los archivos 1 y 2* c4930d7 Tercer commit, hola.py* 6e99e73 Segundo commit, hola.py* 1c95e4f Primer commit, hola.py
Eliminar ramos
A ideia de um branch é criá-lo para desenvolver uma nova funcionalidade ou característica de forma que não afete o restante da equipe de desenvolvimento. Portanto, quando isso é alcançado, ele é mesclado com o branch principal. Assim, depois da mesclagem, não faz mais sentido manter o branch, então ele precisa ser excluído, mas isso será feito de maneira diferente se o branch tiver sido mesclado ou não com o principal.
Excluir ramos que foram mesclados (git branch -d <ramo>)
Para eliminar um ramo sobre o qual já foi feita a fusão com o principal, basta fazer git branch -d <ramo> ou git branch --delete <ramo>. Vamos eliminar o último ramo que criamos e fundimos
InputPython!cd notebook_git && git branch -d rama_con_conflictoCopied
Eliminada la rama rama_con_conflicto (era 32851c3).
Se agora listarmos todos os ramos, podemos ver que já não teremos rama_con_conflicto
InputPython!cd notebook_git && git branchCopied
branch_fast_forwardbranch_no_fast_forwardbranch_squash* mainnew_branchnew_branch2
Remover branches que não foram mescladas com a branch principal (git branch -D <branch>)
Se tentarmos fazer o mesmo que antes com uma ramificação que nunca foi mesclada com outra, obteremos um erro
Vamos criar uma nova branch, vamos fazer um commit e não vamos mesclá-la
InputPython!cd notebook_git && git branch branch_sin_fusionCopied
InputPython!cd notebook_git && git switch branch_sin_fusionCopied
Cambiado a rama 'branch_sin_fusion'
InputPython!cd notebook_git && touch file4 && git add file4 && git commit -m "file4"Copied
[branch_sin_fusion 9506b0a] file41 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 file4
InputPython!cd notebook_git && git switch mainCopied
Cambiado a rama 'main'
Com tudo o que aprendemos até agora, podemos ver que o que fizemos foi criar uma nova ramificação, mudar para ela, criar um novo arquivo, fazer um commit e voltar para a ramificação main. Agora vamos tentar eliminar esta nova ramificação
InputPython!cd notebook_git && git branch -d branch_sin_fusionCopied
error: La rama 'branch_sin_fusion' no ha sido fusionada completamente.Si estás seguro de querer borrarla, ejecuta 'git branch -D branch_sin_fusion'.
Como vemos, ele nos diz que branch_sin_fusion não foi mesclada, por isso não foi eliminada, e que, se temos certeza de que queremos eliminá-la, precisamos fazer git branch -D branch_sin_fusion, então fazemos isso para eliminá-la
InputPython!cd notebook_git && git branch -D branch_sin_fusionCopied
Eliminada la rama branch_sin_fusion (era 9506b0a).
Agora sim foi eliminado
---
➡️ **Continua na Parte 3: repositorios remotos, stash y tags**, onde levarás o teu código para a nuvem e aproveitarás as ferramentas avançadas do Git.