Executando verificação de segurança...
24

Comandos do Git que provavelmente você não conhece


Comandos Modernos do Git e Features que Você Deveria estar Usando

Já se foram os dias em que os comandos básicos do git, como add, commit, push e pull, eram tudo o que usávamos, como se ainda estivéssemos em 2005. No mundo dinâmico do desenvolvimento de software, o git evoluiu significativamente, oferecendo uma série de recursos avançados que muitos de nós podem não estar aproveitando totalmente.

Como engenheiros de software que interagem com o git diariamente, é essencial manter-se atualizado com as últimas melhorias e ferramentas que ele oferece.

Este conteúdo visa iluminar alguns dos comandos modernos e menos conhecidos do git que foram introduzidos ao longo dos anos, que poderiam simplificar significativamente nosso fluxo de trabalho e aumentar nossa produtividade.

Vamos explorar esses novos comandos do git e descobrir como eles podem transformar nossa experiência diária de programação.

Switch

A partir de 2019, mais precisamente, introduzido na versão 2.23 do Git, temos o comando git switch, que podemos usar para alternar entre branches:

git switch outra-ramificacao
git switch -  # Voltar para a ramificação anterior, similar ao "cd -"
git switch ramificacao-remota  # Alternar diretamente para uma ramificação remota e começar a rastreá-la

Isso é interessante, mas nós já estamos alternando entre branches no Git desde sempre usando o git checkout, então por que a necessidade de um comando separado?

O git checkout é um comando bastante versátil - ele pode (entre outras coisas) restaurar arquivos específicos ou até commits específicos, enquanto o novo git switch serve apenas para mudar de ramificação. Além disso, o switch realiza verificações de consistência adicionais que o checkout não faz, por exemplo, o switch abortaria a operação se isso levasse à perda de alterações locais.

Restore

Outro novo subcomando/recurso adicionado na versão 2.23 do Git é o git restore, que podemos usar para restaurar um arquivo para a última versão "commitada":

# Desfazer mudanças feitas em um arquivo, equivalente a "git reset some-file.py"
git restore --staged some-file.py

# Desfazer e descartar mudanças feitas em um arquivo, equivalente a "git checkout some-file.py"
git restore --staged --worktree some-file.py

# Reverter um arquivo para algum commit anterior, equivalente a "git reset commit -- some-file.py"
git restore --source HEAD~2 some-file.py

Os comentários no trecho acima explicam o funcionamento de vários comandos git restore.

Falando de forma geral, o git restore substitui e simplifica alguns dos casos de uso do git reset e git checkout, que são recursos já sobrecarregados. Veja também esta seção da documentação para comparação entre revert, restoreereset`.

Sparse Checkout

O próximo recurso é o git sparse-checkout, uma funcionalidade um pouco mais obscura que foi adicionada no Git 2.25, lançado em 13 de janeiro de 2020.

Suponha que você tenha um grande monorepositório, com microserviços separados em diretórios individuais, e comandos como checkout ou status são extremamente lentos devido ao tamanho do repositório, mas talvez você realmente só precise trabalhar com um único subdiretório/árvore.

Bem, o `git sparse-checkout vem para o resgate:

$ git clone --no-checkout https://github.com/derrickstolee/sparse-checkout-example
$ cd sparse-checkout-example
$ git sparse-checkout init --cone  # Configura o git para combinar apenas arquivos no diretório raiz
$ git checkout main  # Faz checkout apenas dos arquivos no diretório raiz
$ ls
bootstrap.sh  LICENSE.md  README.md

$ git sparse-checkout set service/common

$ ls
bootstrap.sh  LICENSE.md  README.md  service

$ tree .
.
├── bootstrap.sh
├── LICENSE.md
├── README.md
└── service
    ├── common
    │   ├── app.js
    │   ├── Dockerfile
    ... ...

No exemplo acima, primeiro clonamos o repositório sem realmente fazer o checkout de todos os arquivos. Em seguida, usamos git sparse-checkout init --cone para configurar o git para combinar apenas arquivos no diretório raiz do repositório. Assim, após executar o checkout, temos apenas 3 arquivos em vez de toda a árvore. Para baixar/fazer checkout de um diretório específico, usamos git sparse-checkout set ...

Como já mencionado, isso pode ser muito útil ao trabalhar localmente com repositórios grandes, mas é igualmente útil em CI/CD para melhorar o desempenho de um pipeline, quando você deseja construir/implementar apenas parte do monorepositório e não há necessidade de fazer checkout de tudo.

Para uma descrição detalhada sobre sparse-checkout, veja este artigo.

Worktree

Não é incomum que alguém precise trabalhar em múltiplas funcionalidades em uma única aplicação (repositório) ao mesmo tempo, ou talvez um bug crítico apareça enquanto você está no meio do desenvolvimento de uma solicitação de funcionalidade.

Nessas situações, você precisa ter múltiplas versões/ramificações do repositório clonadas, ou precisa guardar/descartar o que estiver trabalhando no momento. A resposta para essas situações é o git worktree, lançado em 24 de setembro de 2018:

git branch
# * dev
# master

git worktree list
# /.../some-repo  ews5ger [dev]

git worktree add -b hotfix ./hotfix master

# Preparando worktree (nova branch 'hotfix')
# HEAD agora está em 5ea9faa Commit assinado.

git worktree list
# /.../test-repo         ews5ger [dev]
# /.../test-repo/hotfix  5ea9faa [hotfix]

cd hotfix/  # Worktree limpo, onde você pode fazer suas mudanças e enviá-las

Este comando permite que tenhamos múltiplas ramificações do mesmo repositório conferidas ao mesmo tempo. No exemplo acima, temos 2 branches, dev e master. Digamos que estamos trabalhando em uma funcionalidade na branch dev, mas nos pedem para fazer uma correção de bug urgente. Em vez de guardar as mudanças e resetar a branch, criamos um novo worktree no subdiretório ./hotfix a partir da branch master. Podemos então ir para esse diretório, fazer nossas mudanças, enviá-las e retornar ao worktree original.

Para um artigo mais detalhado, veja este texto.

Bisect

Por último, mas não menos importante, o git bisect, que não é tão novo assim (Git 1.7.14, lançado em 13 de maio de 2012), mas muitas pessoas ainda utilizam apenas recursos do git de cerca de 2005, então acho que vale a pena mencionar de qualquer forma.

Conforme a página de documentação descreve: git-bisect - Utilize a busca binária para encontrar o commit que introduziu um bug:

git bisect start
git bisect bad HEAD  # Indique o commit com problema
git bisect good 479420e  # Indique um commit que você sabe que funciona
# Bissectando: restam 2 revisões para testar depois desta (aproximadamente 1 passo)
# [3258487215718444a6148439fa8476e8e7bd49c8] Refatoração.

# Teste o commit atual...
git bisect bad  # Se o commit não funcionar
git bisect good # Se o commit funcionar

# O Git bisecta a metade esquerda ou direita do intervalo com base no último comando
# Continue testando até encontrar o responsável

git bisect reset  # Retorna ao commit original

Começamos explicitamente a sessão de bissecção com git bisect start, após o qual fornecemos o commit que não funciona (provavelmente o HEAD) e o último commit ou tag que sabemos que funciona. Com essa informação, o git fará checkout de um commit no meio do caminho entre o commit "ruim" e o "bom". Neste ponto, precisamos testar se essa versão tem o bug ou não, então usamos git bisect good para informar ao git que funciona ou git bisect bad se não funcionar. Continuamos repetindo o processo até que não restem commits e o git nos informará qual commit introduziu o problema.

Recomendo consultar a página de documentação, que mostra mais algumas opções para o git bisect, incluindo visualização, repetição ou pulo de commits.

Conclusão

Se você procurar por algum problema relacionado ao git, é muito provável que acabe em uma pergunta no StackOverflow com uma resposta que possui milhares de votos positivos. Embora essa resposta provavelmente ainda seja válida, ela pode estar desatualizada, pois foi escrita há 10 anos. Portanto, pode existir uma maneira melhor, mais simples e fácil de fazer isso. Então, quando enfrentar algum problema com o git, recomendo verificar a documentação do git para comandos mais recentes, todos com excelentes exemplos, ou explorar as páginas do manual para descobrir muitas opções e flags que foram adicionadas aos comandos clássicos ao longo dos anos.

Créditos ao autor: Martin Heinz, confira na íntegra o conteúdo (link)

Carregando publicação patrocinada...
5

Muito bom!

Complementando: sobre os comandos switch e restore, eu já fiz este post. Vale lembrar que até hoje, a documentação oficial (aqui e aqui) ainda diz que eles são comandos experimentais e podem mudar. De qualquer forma, é interessante conhecê-los, pois se um dia deixarem de ser experimentais, vc não será pego de surpresa.


Por fim, já que a ideia é ir além do básico, tem dois posts meus que falam sobre detalhes internos do Git, e que ajudam muito a entender melhor como ele funciona:

1
2
1
2

Hoje em dia, o ohmyzsh salva muito a minha vida. Realizar uma sequência de comandos como "checkout fetch pull checkout merge push" com gcd && gf && gl && gco <branch> && gm develop && gp é simplesmente incrível.

Mas o que mais me surpreendeu foi a descoberta de comandos ainda mais simples e eficientes, como o gprom. Esse comando basicamente executa um git pull --rebase origin main, evitando alguns merges desnecessários durante a sincronização.

E o melhor de tudo é o gcn!, que é uma verdadeira salvação quando você comete um commit e acidentalmente esquece de adicionar um arquivo por algum motivo. Em vez de fazer um reset soft, adicionar tudo novamente e reescreve o commit, o gcn! simplifica esse processo de forma eficaz.

E sobre os comandos que exemplificou de switch e restore, tem os queridinhos gsw e grst que descobri recentemente fuçando na DOC do ohmyzsh

Achei interessantíssimo o topico e Git é uma skill que a curva de aprendizado eu considero uma das mais legais, pq em um dia vc ta se batendo pra resetar um commit, da um reset --hard e perde tudo, e no outro ta resolvendo uns conflitasso, dando rebase e squash sem nem sentir.

1

Top demais André!
Hoje em dia os ALIAS ajudam muito na correria insana do dia a dia, isso só é "perigoso" para quem está começando agora na área que já cria esse "vício", mas pra quem já entende o que está fazendo é mel na chupeta 🤌🏻

1

Sim sim, sinto o mesmo com quem já começa utilizando o Sourcetree ou o Git Desktop por exemplo, ou até mesmo o controle de código fonte do VSCode, acaba pulando algumas etapas de entender os comos e por quês e na hora de voltar atrás e aprender é bem difícil.

2