Fluxo de trabalho do Git | Comparar fluxos de trabalho

Comparando fluxos de trabalho

Git é o sistema de controle de versões mais usado hoje em dia. Um fluxo de trabalho do Git é uma receita ou recomendação sobre como usar o Git para realizar o trabalho de maneira consistente e produtiva. Os fluxos de trabalho do Git incentivam os desenvolvedores e as equipes de DevOps a aproveitar o Git com eficácia e estabilidade. O Git oferece muita flexibilidade em como os usuários gerenciam mudanças. Dado o foco do Git em flexibilidade, não há nenhum processo padronizado de como interagir com o Git. Ao trabalhar com uma equipe em um projeto gerenciado pelo Git, é importante ter certeza de que a equipe toda esteja de acordo sobre como o fluxo de mudanças vai ser aplicado. Para garantir que a equipe esteja alinhada, deve ser desenvolvido ou selecionado um acordo sobre o fluxo de trabalho do Git. Há vários fluxos de trabalho do Git divulgados que podem ser uma boa opção para a equipe. Aqui, vamos discutir algumas dessas opções de fluxo de trabalho do Git.

A matriz de possíveis fluxos de trabalho pode dificultar saber onde começar ao implementar o Git no local de trabalho. Esta página fornece um ponto de partida ao pesquisar os fluxos de trabalho mais comuns do Git para equipes de software.

Como você lê, lembre-se de que esses fluxos de trabalho são projetados para serem orientações e não regras concretas. Queremos mostrar o que é possível, então, você pode misturar e combinar aspectos de fluxos de trabalho diferentes para atender às suas necessidades individuais.

O que é um fluxo de trabalho bem-sucedido do Git?

Ao avaliar um fluxo de trabalho para sua equipe, o mais importante é considerar a cultura da equipe. Você quer que o fluxo de trabalho melhore a eficácia da equipe e não seja uma carga que limita a produtividade. Algumas coisas a considerar ao avaliar um fluxo de trabalho do Git são:

  • Este fluxo de trabalho tem escalabilidade para diferentes tamanhos de equipe?
  • É fácil de desfazer erros e enganos com este fluxo de trabalho?
  • Este fluxo de trabalho adiciona alguma carga cognitiva desnecessária à equipe?

Fluxo de trabalho centralizado

Fluxo de trabalho do Git | Repositórios central e local

O Fluxo de trabalho centralizado é um grande fluxo de trabalho do Git para equipes em transição do SVN. Como o Subversão, o Fluxo de trabalho centralizado usa um repositório central para servir como único ponto de entrada para todas as mudanças no projeto. Em vez de tronco, a ramificação de desenvolvimento padrão é chamada de branch main e todas as alterações recebem commit nesta ramificação. Este fluxo de trabalho não requer nenhum outro branch além do branch main.

Fazer a transição para um sistema de controle de versão distribuído pode parecer uma tarefa assustadora, mas você não tem que mudar seu fluxo de trabalho existente para aproveitar o Git. Sua equipe pode desenvolver projetos exatamente da mesma maneira que faz com o Subversão.

No entanto, usar o Git para impulsionar o fluxo de trabalho de desenvolvimento apresenta algumas vantagens sobre o SVN. Em primeiro lugar, dá a cada desenvolvedor sua própria cópia local do projeto inteiro. Este ambiente isolado permite que cada desenvolvedor trabalhe de modo independente de todas as outras mudanças em um projeto — ele pode adicionar confirmações ao repositório local e esquecer completamente sobre desenvolvimentos de upstream até que seja conveniente para ele.

Em segundo lugar, dá a você acesso ao robusto modelo de ramificação e mesclagem do Git. Ao contrário do SVN, as ramificações do Git são projetadas para serem um mecanismo à prova de falhas para integrar o código e compartilhar mudanças entre os repositórios. O Fluxo de trabalho centralizado é semelhante a outros fluxos de trabalho em sua utilização de um repositório hospedado do lado do servidor remoto que os desenvolvedores empurram e puxam. Comparado a outros fluxos de trabalho, o Fluxo de trabalho centralizado não tem nenhum padrão definido de solicitação pull ou ramificação. Um Fluxo de trabalho centralizado geralmente é mais adequado para equipes que estão migrando do SVN para o Git e equipes menores.

Como funciona

Os desenvolvedores começam clonando o repositório central. Em suas próprias cópias locais do projeto, eles editam arquivos e confirmam mudanças como fariam com o SVN; no entanto, essas novas confirmações são armazenadas localmente — elas estão completamente isoladas do repositório central. Isso permite que os desenvolvedores adiem a sincronização de upstream até que estejam em um ponto de interrupção conveniente.

Para publicar as alterações no projeto oficial, os desenvolvedores enviam o branch main local ao repositório central. É o equivalente de svn commit, exceto que ele adiciona todos os commits locais que ainda não estão no branch main central.

Inicializar o repositório central

Fluxo de trabalho do Git: Inicializar o repositório vazio central

Em primeiro lugar, alguém precisa criar o repositório central em um servidor. Se for um novo projeto, você pode iniciar um repositório vazio. Caso contrário, será necessário importar um repositório Git ou SVN existente.

Repositórios centrais devem sempre ser repositórios vazios (eles não devem ter um diretório de trabalho), que podem ser criados da seguinte maneira:

ssh user@host git init --bare /path/to/repo.git

Tenha certeza de usar um nome de usuário SSH válido para user, o domínio ou endereço IP do seu servidor para host e o local em que você gostaria de armazenar o repositório para /path/to/repo.git. Note que, por convenção, a extensão .git é anexada ao nome do repositório para indicar que é um repositório vazio.

Repositórios centrais hospedados

Normalmente, os repositórios centrais são criados por meio de serviços de hospedagem do Git de terceiros, como Bitbucket Cloud ou Bitbucket Server. O processo de início de um repositório vazio discutido acima é entregue para você pelo serviço de hospedagem. O serviço de hospedagem vai disponibilizar um endereço para o repositório central acessar a partir do repositório local.

Clonar o repositório central

Em seguida, cada desenvolvedor cria uma cópia local de todo o projeto usando o comando git clone:

git clone ssh://user@host/path/to/repo.git

Quando você clona um repositório, o Git faz a adição automática de um atalho chamado origem que aponta de volta para o repositório “pai”, sob a suposição de que você vai querer interagir com ele no futuro.

Fazer mudanças e confirmar

Depois que o repositório é clonado localmente, um desenvolvedor pode fazer mudanças usando o processo de confirmação padrão do Git: editar, montar e confirmar. Se você não estiver familiarizado com a área de staging, é uma maneira de preparar uma confirmação sem ter que incluir cada mudança no diretório de trabalho. Isso permite criar confirmações altamente focadas, mesmo que você tenha feito muitas mudanças locais.

git status # View the state of the repo
git add <some-file> # Stage a file
git commit # Commit a file</some-file>

Lembre-se de que, desde que esses comandos criem confirmações locais, John pode repetir esse processo quantas vezes quiser sem se preocupar com o que está acontecendo no repositório central. Isso pode ser muito útil para recursos grandes que precisam ser divididos em partes mais simples, mais atômicas.

Envie novas confirmações para o repositório central

Depois que o repositório local tiver novas mudanças confirmadas, essas mudanças deverão ser enviadas para compartilhamento com outros desenvolvedores no projeto.

 git push origin main

Este comando vai enviar as novas mudanças com commit para o repositório central. Ao enviar as mudanças para o repositório central, é possível que tenham sido enviadas atualizações de outro desenvolvedor que contêm código que entrem em conflito com as atualizações de envio pretendidas. O Git vai imprimir uma mensagem indicando esse conflito. Nesta situação, o git pull deve ser executado primeiro. Este cenário de conflito vai ser expandido na próxima seção.

Como gerenciar conflitos

O repositório central representa o projeto oficial, então, sua história de confirmação deve ser tratada como sagrada e imutável. Se as confirmações locais de um desenvolvedor divergirem do repositório central, o Git recusará enviar suas mudanças porque isso substituiria as confirmações oficiais.

Fluxos de trabalho do Git: Gerenciar conflitos

Antes de o desenvolvedor poder publicar seu recurso, ele precisa buscar as confirmações centrais atualizadas e fazer rebase de suas mudanças na parte de cima delas. Isso é como dizer “Quero adicionar minhas mudanças ao que todo mundo já fez”. O resultado é uma história perfeitamente linear, como nos fluxos de trabalho tradicionais de SVN.

Se as mudanças locais entrarem em conflito direto com commits upstream, o Git vai pausar o processo de rebase para que você possa fazer a resolução manual dos conflitos. O bom do Git é que ele usa os mesmos comandos git status e git add tanto para gerar commits quanto para resolver conflitos de mesclagem. Assim fica fácil para os novos desenvolvedores gerenciarem suas próprias mesclagens. Além do mais, se eles tiverem problemas, no Git é muito fácil abortar todo o rebase e tentar de novo (ou procurar ajuda).

Exemplo

Vamos dar um exemplo geral sobre como uma equipe pequena típica poderia colaborar usando esse fluxo de trabalho. Vamos ver como dois desenvolvedores, John e Mary, podem trabalhar em recursos separados e compartilhar suas contribuições por meio de um repositório centralizado.

John trabalha em seu recurso

Fluxos de trabalho do Git: Editar o processo de recurso de confirmação de montagem

Em seu repositório local, John pode desenvolver recursos usando o processo de confirmação padrão do Git: editar, montar e confirmar.

Lembre-se de que, como esses comandos criam confirmações locais, John pode repetir esse processo quantas vezes quiser sem se preocupar com o que está acontecendo no repositório central.

Mary trabalha em seu recurso

Fluxos de trabalho do Git: Editar o recurso de confirmação de montagem

Ao mesmo tempo, Mary está trabalhando em seu próprio recurso em seu próprio repositório local usando o mesmo processo editar/montar/fazer commit. Como John, ela não se importa com o que está acontecendo no repositório central e não se importa mesmo com o que John está fazendo no repositório local dele, uma vez que todos os repositórios locais são privados.

John publica seu recurso

Fluxos de trabalho do Git: Publicar recurso

Depois que John termina o recurso, ele deve publicar os commits locais no repositório central para que outros membros da equipe possam ter acesso. Ele pode usar o comando git push da seguinte maneira:

 git push origin main

Observe que a origin é a conexão remota com o repositório central que o Git criou quando John o clonou. O argumento main diz ao Git para tentar fazer com que o branch main de origin se pareça com o branch main local. Como o repositório central não foi atualizado desde que John o clonou, nenhum conflito vai ser gerado e o envio vai funcionar como esperado.

Mary tenta publicar seu recurso

Fluxos de trabalho do Git: Enviar erro de comando

Vamos ver o que acontece se Mary tentar enviar seu recurso após John ter publicado com êxito as mudanças dele no repositório central. Ela pode usar exatamente o mesmo comando de envio:

 git push origin main

Mas, como a história local dela diverge do repositório central, o Git vai recusar a solicitação com uma mensagem de erro mais detalhada:

error: failed to push some refs to '/path/to/repo.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Isso impede que Mary substitua as confirmações oficiais. Ela precisa enviar pull das atualizações de John para o repositório dela, integrá-las com suas mudanças locais e depois tentar novamente.

Mary faz o rebase na parte superior da(s) confirmação(ões) de John

Fluxos de trabalho do Git: Rebase de pull do Git

Mary pode usar o git pull para integrar as alterações upstream ao repositório que tem. Este comando é parecido com o svn update — ele envia todo o histórico de commits upstream para o repositório local de Mary e tenta integrar aos commits locais dela:

 git pull --rebase origin main

A opção --rebase diz ao Git para mover todos os commits de Mary para a ponta do branch main depois de o sincronizar com as alterações do repositório central, como mostrado abaixo:

Fluxos de trabalho do Git: Fazer o rebase para o mestre

O pull ainda pode funcionar se você esquecer essa opção, mas seria necessário concluir com uma “confirmação de mesclagem” supérflua toda vez que alguém precisasse sincronizar com o repositório central. Para este fluxo de trabalho, é sempre melhor fazer o rebase em vez de gerar uma confirmação de mesclagem.

Mary resolve um conflito de mesclagem

Fluxos de trabalho do Git: Fazer o rebase sobre confirmações

O rebase funciona transferindo cada commit local para o branch main atualizado, um de cada vez. Ou seja: você captura conflitos de mesclagem de commit em commit em vez de resolver todos eles em um commit de mesclagem em massa. Assim os commits ficam o mais focados possível e o histórico do projeto fica limpo, o que faz com que seja muito mais fácil descobrir onde os bugs foram introduzidos e, se necessário, reverter as mudanças com impacto mínimo sobre o projeto.

Se Mary e John estiverem trabalhando em recursos não relacionados, é improvável que o processo de rebase gere conflitos. Mas se gerar, o Git vai pausar o rebase na confirmação atual e enviar a seguinte mensagem, juntamente com algumas instruções relevantes:

CONFLICT (content): Merge conflict in <some-file>
Fluxos de trabalho do Git: Resolução de conflitos

O importante sobre o Git é que qualquer pessoa pode resolver os próprios conflitos de mesclagem. No exemplo, Mary executaria um simples git status para ver onde está o problema. Arquivos com conflito vão aparecer na seção de Caminhos não mesclados:

# Unmerged paths:
# (use "git reset HEAD <some-file>..." to unstage)
# (use "git add/rm <some-file>..." as appropriate to mark resolution)
#
# both modified: <some-file>

Em seguida, ela vai editar o(s) arquivo(s) da maneira que quiser. Quando estiver feliz com o resultado, ela poderá organizar o(s) arquivo(s) da maneira habitual e deixar o git rebase fazer o resto:

git add <some-file>
git rebase --continue

E isso é tudo o que há para ela. O Git passará para a próxima confirmação e repetirá o processo para qualquer outra confirmação que gere conflitos.

Se você chegar a esse ponto, perceber e não tiver ideia do que está acontecendo, não entre em pânico. Apenas execute o comando a seguir e você voltará para onde começou:

git rebase --abort

Mary publica seu recurso com êxito

Fluxo de trabalho do Git: Sincronizar o repositório central

Depois que terminar de sincronizar com o repositório central, Mary poderá publicar suas mudanças com êxito:

 git push origin main

Onde ir a partir daqui

Como você pode ver, é possível replicar um ambiente de desenvolvimento tradicional do Subversão usando apenas alguns comandos do Git. Isso é excelente para as equipes de transição fora do SVN, mas não aproveita a natureza distribuída do Git.

O Fluxo de trabalho centralizado é ótimo para equipes pequenas. O processo de resolução de conflitos detalhado acima pode formar um gargalo à medida que sua equipe aumentar de tamanho. Se sua equipe estiver confortável com o Fluxo de trabalho centralizado, mas quiser simplificar seus esforços de colaboração, vale a pena explorar os benefícios do Fluxo de trabalho de ramificação de recurso. Ao dedicar uma ramificação isolada a cada recurso, é possível iniciar discussões mais profundas sobre novas adições antes de fazer a integração delas ao projeto oficial.

Outros fluxos de trabalho comuns

O Fluxo de trabalho centralizado é essencialmente um bloco de construção para outros fluxos de trabalho do Git. Os fluxos de trabalho mais populares do Git terão algum tipo de repositório centralizado do qual os desenvolvedores individuais farão envios e enviarão pull. Abaixo, vamos discutir rapidamente alguns outros fluxos de trabalho populares do Git. Esses fluxos de trabalho estendidos oferecem padrões mais especializados em relação ao gerenciamento de ramificações para desenvolvimento de recursos, hot fixes e lançamento eventual.

Ramificação de recurso

A Ramificação de recursos é uma extensão lógica do Fluxo de trabalho centralizado. A ideia central por trás do Fluxo de trabalho de ramificação de recursos é que todo desenvolvimento de recursos deve ocorrer em uma ramificação dedicada em vez de no branch main. Esse encapsulamento facilita para vários desenvolvedores trabalharem em um recurso particular sem perturbar a base de código principal. Assim, o branch main nunca deve conter código quebrado, o que é uma enorme vantagem para ambientes de integração contínua.

Fluxo de trabalho de Gitflow

O Fluxo de trabalho de Gitflow foi publicado pela primeira vez em um blog de 2010 de alto prestígio de Vincent Driessen no nvie. O Gitflow Workflow define um modelo estrito de ramificação projetado em torno do lançamento do projeto. Esse fluxo de trabalho não adiciona nenhum conceito ou comando novo além do exigido para o Fluxo de trabalho de ramificação de recurso. O que ele faz é atribuir funções muito específicas a diferentes ramificações e define como e quando elas devem interagir.

Fluxo de trabalho de bifurcação

O Fluxo de trabalho de bifurcação tem diferenças fundamentais em relação aos outros fluxos de trabalho discutidos neste tutorial. Em vez de usar um único repositório do lado do servidor para funcionar como a base de código “central”, ele dá a cada desenvolvedor um repositório do lado do servidor. Quer dizer que cada colaborador tem não apenas um, mas dois repositórios do Git: um local privado e um público do lado do servidor.

Orientações

Não há nenhum fluxo de trabalho do Git de tamanho único. Como dito antes, é importante desenvolver um fluxo de trabalho do Git que seja uma melhoria de produtividade para a equipe. Além da cultura da equipe, o fluxo de trabalho também deve complementar a cultura da empresa. Recursos do Git, como ramificações e marcadores, devem complementar a programação de lançamento da empresa. Se sua equipe estiver usando o software de gestão de projetos de controle de tarefa, talvez você queira usar ramificações que correspondam às tarefas em andamento. Além desses aspectos, algumas orientações a considerar ao decidir sobre um fluxo de trabalho são:

Ramificações de curta duração

Quanto mais uma ramificação durar separada da ramificação de produção, maior o risco de conflitos de mesclagem e desafios de implementação. Ramificações de curta duração promovem mesclagens e implementações mais limpas.

Minimizar e simplificar reversões

É importante ter um fluxo de trabalho que ajude a impedir, com iniciativa, mesclagens que vão ter que ser revertidas. Um fluxo de trabalho que teste uma ramificação antes de permitir que ela seja mesclada no branch main é um exemplo. No entanto, acidentes acontecem. Então é bom ter um fluxo de trabalho que permita reversões fáceis que não interrompam o fluxo para outros membros da equipe.

Coincidir com a programação de um lançamento

Um fluxo de trabalho deve complementar o ciclo de lançamento de desenvolvimento de software da empresa. Se você planeja lançar várias vezes por dia, vai querer manter o branch main estável. Se a programação de lançamento for menos frequente, talvez você considere a possibilidade de usar marcadores do Git para marcar uma ramificação para uma versão.

Resumo

Neste documento, discutimos fluxos de trabalho do Git. Demos uma olhada mais detalhada em um Fluxo de trabalho centralizado com exemplos práticos. Expandindo o Fluxo de trabalho centralizado, discutimos fluxos de trabalho especializados adicionais. Alguns argumentos principais deste documento são:

  • Não há um fluxo de trabalho específico do Git que atenda a todos os casos
  • Um fluxo de trabalho deve ser simples e melhorar a produtividade da sua equipe
  • Seus requisitos de negócios devem ajudar a formar seu fluxo de trabalho do Git

Para ler sobre o próximo fluxo de trabalho do Git, confira a abrangente divisão do Fluxo de trabalho de ramificação de recurso.

Pronto(a) para aprender Git?

Tente este tutorial interativo.

Comece agora mesmo