Folha de referência do Git [PDF]
(wizardzines.com)- Um PDF que organiza tarefas em que as pessoas costumam travar no Git para consulta rápida, como criação de commits, troca de branches, comparação de alterações, sincronização remota e comandos para desfazer alterações
- O fluxo de trabalho local gira em torno de
git status,git add,git commitegit diff, verificando o estado antes e depois do staging e criando commits - O trabalho com branches usa
git switch,git checkout,git branch,git merge,git rebaseegit cherry-pickpara lidar com criação, troca, merge e rebase - Para explorar o histórico e recuperar alterações, inclui
git log,git blame,git show,git reflog,git resetegit restore; branches, tags,HEADe branches remotas também podem ser usados como referências de commits - Operações com repositórios remotos cobrem o processo de buscar e enviar alterações com
git remote add,git fetch,git pull,git push,git push --force-with-leaseegit push --tags
Iniciar um repositório e verificar o estado atual
- Iniciar um novo repositório:
git init
- Clonar um repositório existente:
git clone $URL
- Verificar a localização e o estado atuais:
git status
Preparar e criar commits
- Adicionar um arquivo não rastreado:
git add $FILE
- Adicionar todos os arquivos não rastreados e alterações não staged:
git add .
- Escolher apenas algumas alterações de um arquivo para staging:
git add -p
- Excluir ou mover um arquivo:
git rm $FILEgit mv $OLD $NEW
- Remover um arquivo do rastreamento do Git sem excluí-lo:
git rm --cached $FILE
- Desfazer todo o staging:
git reset HEAD
- Criar um commit:
git commit- Abre um editor de texto para escrever a mensagem
- Criar um commit especificando a mensagem diretamente:
git commit -m 'message'
- Criar um commit com mensagem incluindo também alterações não staged:
git commit -am 'message'
Trocar e gerenciar branches
- Trocar de branch:
git checkout $NAMEgit switch $NAME
- Criar uma branch:
git checkout -b $NAMEgit switch -c $NAME
- Ver a lista de branches:
git branch
- Ordenar branches pelo commit mais recente:
git branch --sort=-committerdate
- Excluir uma branch:
git branch -d $NAME
- Excluir uma branch à força:
git branch -D $NAME
Explorar histórico e rastrear código
- Ver o histórico de uma branch:
git log main
- Ver em grafo a relação entre duas branches:
git log --graph a b
- Ver o log em uma linha:
git log --oneline
- Ver quem alterou por último cada linha de um arquivo:
git blame $FILENAME
- Ver todos os commits que modificaram um arquivo:
git log $FILENAME
- Encontrar commits que adicionaram ou removeram um texto específico:
git log -S banana
Comparar alterações
- Ver a diferença entre um commit e seu commit pai:
git show $COMMIT_ID
- Ver a diferença entre um commit de merge e os pais mesclados:
git show --remerge-diff $COMMIT_ID
- Ver um resumo do diff:
git diff $COMMIT_ID --statgit show $COMMIT_ID --stat
- Comparar dois commits:
git diff $COMMIT_ID $COMMIT_ID
- Comparar apenas um arquivo específico com um commit:
git diff $COMMIT_ID $FILENAME
- Comparar todas as alterações staged e não staged:
git diff HEAD
- Comparar apenas alterações staged:
git diff --staged
- Comparar apenas alterações não staged:
git diff
Arquivos de configuração e opções
- Arquivo de configuração local do Git:
.git/config
- Arquivo de configuração global do Git:
~/.gitconfig
- Lista de arquivos a ignorar:
.gitignore
- Definir uma opção de configuração:
git config user.name 'Julia'
- Definir uma opção global:
git config --global ...
- Adicionar alias:
git config alias.st status
- Ver opções de configuração disponíveis:
man git-config
Editar histórico e restaurar arquivos
- Desfazer o commit mais recente, mantendo o diretório de trabalho como está:
git reset HEAD^
- Desfazer um rebase que falhou:
git reflog BRANCHNAMEgit reset --hard $COMMIT_ID
- Unificar os últimos 5 commits em um só:
git rebase -i HEAD^^^^^^- Mude
pickparafixupnos commits a serem unificados
- Trazer a versão de um arquivo de outra branch ou commit:
git checkout $COMMIT_ID $FILEgit restore $FILE --source $COMMIT_ID
- Alterar a mensagem do commit ou adicionar um arquivo esquecido:
git commit --amend
Juntar branches
- Fazer um fast-forward merge para atualizar a branch atual com outra branch:
git switch maingit merge banana
- Copiar um commit para outra branch:
git cherry-pick $COMMIT_ID
- Juntar branches divergentes com rebase:
git switch bananagit rebase main
- Juntar branches divergentes com merge:
git switch maingit merge bananagit commit
- Juntar branches divergentes com squash merge:
git switch maingit merge --squash bananagit commit
Repositórios remotos e sincronização
- Adicionar um repositório remoto:
git remote add $NAME $URL
- Fazer push da branch
mainpara o remotoorigin:git push origin main
- Enviar uma branch pela primeira vez para
origine configurar a branch de rastreamento:git push -u origin $NAME
- Fazer push da branch atual para a branch remota rastreada:
git push
- Force push:
git push --force-with-lease
- Fazer push de tags:
git push --tags
- Buscar alterações sem modificar a branch local:
git fetch origin main
- Fazer fetch de todas as branches:
git fetch --all
- Após o fetch, fazer rebase na branch atual:
git pull --rebase
- Após o fetch, fazer merge na branch atual:
git pull origin maingit pull
Formas de apontar para commits
- No lugar de
$COMMIT_ID, é possível usar várias referências:- Branch:
main - Tag:
v0.1 - ID do commit:
3e887ab - Branch remota:
origin/main - Commit atual:
HEAD - Commit de 3 versões atrás:
HEAD^^^ - Commit de 3 versões atrás:
HEAD~3
- Branch:
Descartar alterações
- Excluir tanto as alterações staged quanto as não staged de um arquivo:
git checkout HEAD $FILE
- Excluir alterações não staged de um arquivo:
git checkout $FILE
- Excluir todas as alterações staged e não staged:
git reset --hard
- Colocar alterações staged e não staged no stash:
git stash
- Excluir arquivos não rastreados:
git clean
1 comentários
Opiniões no Hacker News
Há alguns comandos que são verdadeiras joias escondidas:
git diff --stagedmostra a diferença entre o último commit e o que está atualmente em staging, então é bom para verificar se só entrou o que você pretendia ao adicionar arquivos ou hunks com precisãogit log <file>mostra apenas os commits em que aquele arquivo foi alterado, reduzindo a necessidade de vasculhar todo ogit log, e é especialmente útil em arquivos que não mudam com frequênciaAo usar
git add --patch, se você quiser escolher com mais granularidade do que os hunks que o Git separou, vale experimentar a opçãoe. Ela explica como incluir/excluir linhas individuais, então não é preciso decorargit diff --stagedé um alias degit diff --cached. Usocachedhá anos, masstagedé bem mais intuitivo. Só não sei se vou conseguir apagar essa memória muscularSe tiver interesse, pode dar uma olhada ou sugerir aliases: https://gitlab.com/Falimonda/gitrc
git config --global commit.verbose true, o Git insere automaticamente o diff em staging na área de comentários do editor da mensagem de commitUm dos meus comandos favoritos que não está na lista é
git log -LstartLine,endLine:fileNameComo um
git blameestendido, ele mostra como as linhas especificadas mudaram ao longo do tempo e quem as alterou. Ele acompanha mesmo quando os números de linha mudam ou o arquivo é movidoResponde a perguntas como “quem fez isso, quando e por quê?” ou “desde quando está assim?”
Isso me lembra a frase de Phil Karlton: “Há apenas duas coisas difíceis em ciência da computação: invalidação de cache e dar nomes às coisas.”
Desse ponto de vista, o nome do comando Git ser
blamesempre me pareceu bem estranho, e eu não fui o único a pensar assimWhat does 'git blame' do? https://stackoverflow.com/questions/31203001/what-does-git-blame-do
Blame someone else for your bad code https://news.ycombinator.com/item?id=27963868
Git blame should be called git credit https://dev.to/damcosset/git-blame-should-be-called-git-credit-27h5
Does Git Blame sound too negative? https://www.reddit.com/r/ProgrammerHumor/comments/r5lzyo/does_git_blame_sound_too_negative_just_look_up/
git,blameparece um nome alinhado à marcablameporwho. Na verdade, como sou usuário hardcore de Vim, uso simplesmentewGostei da forma como aprendi Git. No começo, comecei pelo Sourcetree, uma GUI Git de terceiros, que era muito fácil de usar e entender
Depois passei para o
git gui, mas essa etapa pode ser pulada. Mais tarde, fiquei com preguiça de abrir a UI e aprendi os comandos no terminalRecomendo para iniciantes em Git, mas é apenas minha experiência n=1
clone,pull,commitepush, e até agora isso foi suficiente. Git também pode ser simples assim. Claro, se precisar, dá para aprender usos mais complexosNo momento em que comecei a usar Magit, comecei a entender Git
Só tenho elogios ao Sublime Merge
Fico me perguntando se há razões históricas para o Git ser desnecessariamente complexo
Ao ver esta cheat sheet, essa complexidade fica ainda mais evidente
O fato de ele ter passado a ser usado tão amplamente talvez tenha sido um “acidente feliz”, ou talvez uma infelicidade. O GitHub teve um grande mérito em popularizar o Git com “hospedagem Git gratuita”, mas não acho que o Git seja o sistema de controle de versão ideal para muitos projetos
Como ele foi feito para Linus e para o Linux, a terminologia e os fluxos de trabalho às vezes parecem o inverso dos sistemas de controle de versão comuns. O nome
Pull Requesttambém vem do desenvolvimento do Linux, porque Linus ou um mantenedor puxa as alterações para a árvore do kernel. Em outros sistemas, costuma-se chamar deMerge Request, o que é muito mais lógico, já que as alterações são mescladas à árvore independentemente de onde vieramO Git era praticamente o único sistema de controle de versão distribuído open source capaz de lidar rapidamente com bases de código enormes, e por isso a inércia também cresceu nas grandes empresas
Para projetos pessoais, prefiro muito mais Mercurial e de fato o uso, mas, ao usar Hg em uma base de código grande como o Android AOSP, ele engasga bastante. O Mercurial tem uma interface de usuário e um sistema de comandos melhores, e também tem um recurso que sobe um servidor web na hora para visualizar a árvore de alterações, mas, por ser escrito em Python, seu desempenho e escalabilidade não são ideais
git checkout, tornando a experiência do usuário mais confusaNas versões mais recentes do Git, o custo de adicionar novos subcomandos diminuiu, e eles começaram a incluir comandos mais específicos, como
git switchlog,add,commit,pullepush. Também existem ferramentas com GUISinceramente, não acho que o Git seja tão complexo para tarefas comuns. Ele só tem muitos recursos poderosos disponíveis quando você precisa deles
Os desenvolvedores do kernel precisavam se comunicar de forma descentralizada e trabalhar em cima do trabalho uns dos outros. Como se trabalha em um projeto em que 15.000 pessoas escrevem código? O Git foi criado para esse propósito
Ele é tão complexo quanto precisa ser para suportar o fluxo de trabalho para o qual foi projetado. É fácil criar uma ferramenta mais simples, mas aí ela não suportaria fluxos complexos como o desenvolvimento do kernel Linux. Portanto, ele não é desnecessariamente complexo, mas é verdade que é mais complexo do que o necessário para usos simples
Se você precisa de um front-end menos complexo, há muitas ferramentas que tornam o Git mais fácil de usar. Se você não é desenvolvedor de software em tempo integral, eu não recomendaria usar Git diretamente. Mas, se você é desenvolvedor em tempo integral, vale a pena investir tempo para entender os conceitos internos; depois que você entende, o Git é bastante elegante pelo que faz
Eu não diria que saber Git define se alguém é qualificado como desenvolvedor de software, mas, se entender por conta própria como sistemas fundamentais como esse funcionam não lhe dá dopamina, talvez esta área não seja do seu gosto. E tudo bem: há coisas que combinam ou não com cada pessoa
Para aprender a se movimentar no Git, recomendo https://learngitbranching.js.org. Claro, https://xkcd.com/1597/ também se aplica
Eu não conhecia
git add -p, mas é realmente útil-p,--patchpermite escolher interativamente hunks de patch entre o índice e a árvore de trabalho para adicioná-los ao índice. Isso dá a chance de revisar as diferenças antes de adicionar as alterações ao índiceAlgo que eu acrescentaria aqui é a combinação de
git commit --fixup $COMMIT_IDcomgit rebase -i upstream/master --autosquashVirou parte essencial do meu fluxo de trabalho recente. O exemplo de Julia usa
HEAD^^^^^para fazer rebase dos 5 commits anteriores, mas até pouco tempo eu usavaHEAD~5. Só que agora descobri que posso simplesmente fazer rebase de todos os commits até oHEADdo upstreamgit commit --fixup $COMMIT_IDimediatamente. Eu sempre criava pequenos commits de correção como “oops GET users/me” e, no próximo rebase interativo, movia manualmente para fazer fixup, mas esse jeito é muito melhor“Juntar os últimos 5 commits em um só:
git rebase -i HEAD^^^^^^” acho que deveria sergit rebase -i HEAD~5Partindo do pressuposto de que você quer fazer rebase apenas de um histórico linear
https://stackoverflow.com/questions/2221658/whats-the-difference-between-head-and-head-in-git
A maior ficha caiu no momento em que entendi que todos os commits ainda permanecem internamente. Tags e branches apenas apontam para commits, e o commit para o qual um branch apontava antes também não desapareceu
Muitos comandos — talvez quase todos — são não destrutivos, então é fácil referenciar o estado anterior de um branch
Eu já tinha visto
git reflog, mas usava principalmente para lembrar “qual era mesmo aquele branch em que eu tinha trabalhado antes?”Acabei desenvolvendo um medo meio saudável de operações que podiam me jogar no meio de uma resolução de conflitos indesejada. Normalmente os conflitos aconteciam porque eu referenciava o commit ou branch errado
Esse medo não sumiu completamente, mas pelo menos fiquei bem mais confortável em recuperar trabalhos antigos no meio de operações como rebase
Se não sei se alguma operação vai gerar conflito, simplesmente tento e vejo. Se der conflito, resolvo, reverto a operação que criou o conflito, ou crio um novo commit em outro lugar e deixo o conflito para lidar depois
Se já sei que vai dar conflito, duplico o branch relacionado e tento ajustá-lo antes, ou executo a operação conflitante e passo pelo processo de resolução. Se a resolução ficar bagunçada, posso reverter só parte dela e continuar tentando, deixar para depois e fazer outra coisa, ou descartar a árvore inteira
Falando sem rodeios, é preciso deixar o Git de lado e olhar para o JJ
https://martinvonz.github.io/jj/v0.17.1/
Acho que até o Linus considera a UI do Git péssima. O fluxo de trabalho do JJ é excelente
Dito isso, além de ter mexido um pouco, ainda não usei a fundo em trabalho real, então é difícil cravar