|
| 1 | +# Como tratar conflitos no Git? (Lays Rodrigues) |
| 2 | + |
| 3 | +Em nosso dia a dia de desenvolvimento inevitavelmente vamos ter que lidar com conflitos no Git. |
| 4 | +Segundo a definição do [Github Docs](https://docs.github.com/en/github/collaborating-with-pull-requests/addressing-merge-conflicts/about-merge-conflicts) um conflito "é criado quando você faz um _merge_ entre _branches_ que possuem commits concorrentes e o Git precisa da sua ajuda para decidir quais alterações incorporar na _merge_ final." |
| 5 | +Ou seja, você alterou arquivos em sua _branch_ e ao tentar fazer o merge na _main_ ou em outra _branch_, os arquivos que sofreram alteraçães também foram modificados na mesma linha ou totalmente por outra pessoa e portando você precisa decidir se vai manter suas alterações ou as de terceiros. |
| 6 | + |
| 7 | +## Como causar confitos? |
| 8 | + |
| 9 | +Primeiramente vamos criar um cenário de conflito e analisá-lo. |
| 10 | + |
| 11 | +Executaremos em nosso terminal os seguintes comandos: |
| 12 | + |
| 13 | +```sh |
| 14 | +# Comandos para criar e entrar em um diretório |
| 15 | +mkdir meu_conflito && cd meu_conflito |
| 16 | +# Aqui estamos iniciando o git criando a branch main |
| 17 | +git init |
| 18 | +echo "# Este é meu arquivo novo" >> new_file.md |
| 19 | +# Aqui estamos dizendo para o git que temos um novo arquivo |
| 20 | +git add new_file.md |
| 21 | +# Aqui estamos salvando este novo arquivo no git |
| 22 | +git commit -m "Adicionando o novo arquivo" |
| 23 | +# Este comando cria uma nova branch com o nome gera_conflito |
| 24 | +git checkout -b gera_conflito |
| 25 | +echo "# Este é meu texto original =)" >> new_file.md |
| 26 | +# Aqui estamos dizendo para o git que temos alteração em nosso arquivo |
| 27 | +git add new_file.md |
| 28 | +# Aqui estamos salvando as alterações do arquivo no git |
| 29 | +git commit -m "Atualizando o arquivo" |
| 30 | +# Agora estamos voltando a nossa branch inicial |
| 31 | +git checkout main |
| 32 | +echo "# Este texto vai causar um conflito D:" >> new_file.md |
| 33 | +# Aqui estamos realizando uma alteração passível de gerar conflito |
| 34 | +git commit -m "Commit causador de conflito" |
| 35 | +# Voltemos a nossa branch de trabalho |
| 36 | +git checkout gera_conflito |
| 37 | + |
| 38 | +# Comando para realizar um rebase entre gera_conflito e a main |
| 39 | +git rebase main |
| 40 | +# Comando para realizar um merge entre gera_conflito e a main |
| 41 | +git merge main |
| 42 | +``` |
| 43 | + |
| 44 | +### Git Rebase |
| 45 | +No cenário apresentado na imagem abaixo, simulamos o evento de _rebase_ entre duas _branches_. Este exemplo foi feito no VSCode que possui ferramentas que nos auxiliam no tratamento de conflitos. |
| 46 | + |
| 47 | +**Fluxo representando o git rebase** |
| 48 | + |
| 49 | + |
| 50 | +Agora vamos detalhar os elementos presentes nesta imagem. |
| 51 | + |
| 52 | +O bloco entre `<<<<<<< HEAD (Current Change)` e o `=======` destacado em tons de **verde**, representa as alterações pertencentes ao commit na sua _branch_ atual, e o bloco a partir deste último até `>>>>>>> (Commit causador de conflito) (Incoming Change)` destacado em tons de **azul** representa as alterações que o _commit_ da _branch_ para a qual você está realizando o _rebase_ possui. |
| 53 | +Resumidamente o comando `rebase` avalia qual o último _commit_ as duas _branches_ possuem em comum, e a partir desse puxa todos os _commits_ na _branch_ `main` e depois que puxar todos esses _commits_, adiciona os _commits_ relacionados a `gera_conflito`. |
| 54 | + |
| 55 | +No diagrama abaixo temos representados dois cenários. O Cenário I representa nosso estado atual entre as _branches_: Temos o bloco _A_ que concentra o grupo de _commits_ realizados na _branch_ `gera_conflito`, e no bloco _B_ o grupo de _commits_ realizados na _branch_ `main`. No segundo cenário representamos o que seria o fluxo de sucesso, onde conseguiríamos trazer tranquilamente as mudanças da `main` para `gera_conflito`, mas como estamos simulando o cenário de conflito, os blocos _A_ e _B_ contém mudanças conflitantes entre si. |
| 56 | + |
| 57 | + |
| 58 | +### Git Merge |
| 59 | +Alternativamente ao comando _rebase_ temos o comando _merge_, e a simulação do nosso cenário de conflito vem a seguir: |
| 60 | + |
| 61 | +**Fluxo representando o git merge** |
| 62 | + |
| 63 | + |
| 64 | +Visualmente a diferença está na mensagem destacada no bloco **azul**, no cenário de _rebase_ é destacado qual é o _commit_ que causou o conflito, e no cenário de _merge_ é destacado qual o _branch_ que causou o conflito. |
| 65 | + |
| 66 | +### Ok, o que eu faço agora? |
| 67 | + |
| 68 | +Em ambos os cenários temos dois _commits_ que editaram a mesma linha de arquivo, e o _git_ não sabe o que fazer, já que como mostra o diagrama da seção anterior, os dois _commits_ estão no mesmo nível e sobreescreveram o mesmo arquivo. Portanto é nos dada a opção de qual caminho escolher: Se eu permaneço com a alteração do meu _branch_ `gera_conflito` ou se eu escolho manter a alteração da _branch_ `main`. |
| 69 | + |
| 70 | +Neste caso vou permanecer com as alterações que vieram da `main`, portanto selecionei nas opções do meu editor o fluxo do `Accept Incoming Change` ou "Aceitar a mudança recebida", que diz para o meu editor que eu gostaria de aceitar as alterações que estão vindo da _branch_ `main`, onde automaticamente todo o texto entre as linhas 1 e 3, e a linha 5 serão apagados, restando somente a linha 4. Se o seu editor não possuir esse tipo de ferramenta auxiliar, basta você deletar as linhas mencionadas e salvar o arquivo. |
| 71 | + |
| 72 | +Existem mais dois fluxos que você pode escolher no momento de tratar o seu conflito: |
| 73 | +- `Accept Current Change` ou "Aceitar a mudança atual", que em nosso caso apagaria a linha 1 e da 3 em diante. |
| 74 | +- `Accept Both Changes` ou "Aceitar ambas as mudanças", que em nosso caso apagariam as linhas 1, 3 e 6. |
| 75 | + |
| 76 | +O fluxo ideal varia para cada tipo de cenário deve ser avaliado na correção do conflito. |
| 77 | + |
| 78 | +### Vamos resolver o conflito |
| 79 | + |
| 80 | +Após salvar o arquivo, vamos ao terminal e vamos dizer para o _git_ que você já resolvemos o nosso conflito com os seguintes comandos: |
| 81 | + |
| 82 | +```sh |
| 83 | +git add new_file.md |
| 84 | +# No cenário do rebase |
| 85 | +git rebase --continue |
| 86 | +# No cenário do merge |
| 87 | +git merge --continue |
| 88 | +``` |
| 89 | + |
| 90 | +Como dissemos no início deste capítulo, o tratamento de conflitos é inevitável em nossa jornada de solucionadores de problemas. Cada conflito é único e existem algumas formas de criá-los e resolvê-los. Esperamos que este capítulo tenha lhe dado uma base inicial para entender como nós podemos juntar alterações feitas em _branches_ diferentes e o que fazer quando o conflito surgir. |
| 91 | + |
| 92 | +Fique a vontade para submeter um _Pull Request_ para melhorar ou adicionar o conteúdo descrito aqui. Só cuidado com o conflito! |
| 93 | + |
| 94 | +> Para mais informações sobre a diferença entre _rebase_ e _merge_ consulte [este link](https://www.atlassian.com/git/tutorials/merging-vs-rebasing). |
0 commit comments