Tenho notado que bastante gente tem tido dificuldade de usar o Git e o Github quando vem contribuir no CodeCracker. Não é exatamente complicado, mas a documentação que existe pela web, apesar de muito boa, é incompleta, e acaba ficando dividida em diversos lugares diferentes (sugiro ler a excelente Github Flow, do próprio Github), e geralmente não são em português. A ideia desse post é resolver isso. O que eu vou escrever aqui vale pro CodeCracker mas vale também pra qualquer projeto open source (ou não) que estiver no Github.
Se você não conhece o CodeCracker, sugiro ler, nessa ordem:
- Visão geral do projeto CodeCracker, post do Elemar
- História do projeto, meu, aqui nesse blog mesmo
- Como construir um analyzer, um code fix, e como depurar, também do Elemar
- Porque analisadores com Roslyn, do Igor Abade
Se tiver um pouco mais de tempo, ouça o podcast sobre o projeto, que gravamos pro Tecnoretórica. Tem o vídeo da conversa no youtube também, se você quiser nos ver. 🙂
Começando: clonando o projeto
A primeira coisa que você tem que fazer é forkar o projeto. Fácil, só ir até o Github do projeto e clicar no botão de fork do Github, no canto superior direito:
Isso vai criar uma cópia do estado atual do projeto na sua conta. Por exemplo, o meu username no Github é “giggio”, a minha cópia, portanto, fica em https://github.com/giggio/code-cracker.
É esse repositório que você vai clonar, não o repositório do Github. Esse repositório é seu, você pode fazer o que quiser com ele, e tem permissão de criar novos commits nele, fazendo pushs.
Clone seu repositório. Você pode fazer isso de várias formas:
Na linha de comando, vá até o canto direito e copie a url do projeto:
Vá até a linha de comando e digite o comando de clonar. Prefira o Powershell com a extensão posh-git, ou melhor ainda, conemu ou cmder. Fica a dica. Esse é o que eu faria para o meu repositório.
git clone https://github.com/giggio/code-cracker.git
Se eu estiver no diretório c:\temp isso vai criar o diretório c:\temp\code-cracker.
Você também pode clonar usando o Github for Windows, veja o primeiro botão na imagem acima onde temos o endereço de clone. Ou no próprio Visual Studio diretamente, ou usando a extensão do Github para Visual Studio 2015, ou ainda usando o segundo botão, veja ele também na imagem acima.
Eu gosto do suporte a Git do Visual Studio, mas gosto mais ainda da linha de comando. Os exemplos aqui serão na linha de comando, mas se houver equivalente na extensão de VS nesse momento vou mostrá-lo também.
Com isso você já tem o projeto na sua máquina. Mas você ainda não pode começar a trabalhar. Você ainda precisará criar um branch. Mas antes precisamos do nome do branch, e isso depende da issue que você vai trabalhar.
Escolhendo um issue
Pra escolher uma issue pra trabalhar, vá até os issues do Github do CodeCracker. Lá faça um filtro por issues com a tag “up for grabs”:
Vão sobrar na listagem somente os itens que você pode escolher. Os outros ou não estão prontos (veja aqui nossa Definition of Ready – DoR), ou já estão sendo trabalhados ou direcionados pra alguém.
O link direto para as issues up for grabs é esse: https://github.com/code-cracker/code-cracker/labels/up-for-grabs
Algumas das issues são bugs, outras são criações de novos analisadores e code fixes. Algumas são de C#, outras de VB. E algumas são “itens guarda-chuva”, onde uma issue agrega diversas outras. Essas são as que temos lá hoje:
Se você está começando e ainda não conhece bem o Roslyn, você pode começar pegando mais leve. Algumas sugestões são começar por um bug, ou ajudando na documentação, ajudando na tradução (pro Português, por exemplo), ou ajudando a escrever novos issues.
Escolha um issue. Clique na issue, leia, confirme que ninguém está trabalhando nela. Se você entendeu e gostou do issue, basta escrever um comentário dizendo que quer trabalhar nela. Quando eu ou os outros mantenedores do projeto virem o comentário nós retiraremos a tag de up for grabs, e vamos marcar o issue como em andamento (Working). Vamos também te acrescentar no time de colaboradores, e te colocar como responsável da issue. Você pode agora começar a trabalhar nela. Esse processo garante que não teremos mais de uma pessoa trabalhando na mesma issue, onde uma acabaria perdendo todo o trabalho.
Criando um branch
Pra criar um branch é fácil. Vá até o projeto e escreva na linha de comando:
git checkout -b nome-do-branch
O nome do branch você escolhe de acordo com a issue. Ele não importa muito pra ninguém além de você, e quando você terminar você vai poder apagar a branch, porque ela será integrada ao branch master. O mais importante é que o branch sempre seja criado a partir do branch master. Pra garantir que você está no master você pode usar o posh-git (veja na janela de powershell acima como o nome do branch aparece no prompt do powershell) ou escrevendo “git status” na linha de comando.
Você também pode fazer isso no Visual Studio. Vá até o Team Explorer. Ele estará assim:
Clique em Branches, ficará parecido com isso:
Clique com botão direito no branch master e selecione “New Local Branch from…”, e dê um nome pro seu branch:
Ao criar o branch no Visual Studio ou na linha de comando você já é colocado nele.
Pra trocar entre o branch master e o novo branch na linha de comando, basta escrever:
git checkout master git checkout nome-de-branch
Use o “git checkout –“ pra alterar rapidamente para o último branch antes do atual.
No Visual Studio basta clicar duas vezes sobre o nome do branch.
Se você errou o nome do branch tem que apagar ele e criar de novo. Cuidado, porque se você não conhece bem o git você pode não conseguir recuperar os seus commits, então não faça isso se não tiver colocado um novo branch onde você estava.
Pra apagar, vá até o branch master, e em seguida apague o outro branch:
git checkout master git branch -d nome-do-branch
O Git não vai deixar você apagar o branch se ele não estiver integrado à master ou a algum outro branch. Fica de lição de casa descobrir como fazer isso nessa situação. Dica: se você digitar “git help branch” o Git te mostra o que cada opção do comando faz.
No Visual Studio é super simples apagar, vá ao branch master e clique com botão direito no branch que quer apagar, e selecione Delete:
Com isso você já pode começar a escrever seu analisador e code fix. Leia os posts do Elemar e depois vou falar mais sobre ele. Esse post é sobre o processo.
Comitando
Pra fazer um commit no git você escreve na linha de comando:
git commit -m "Minha mensagem de commit"
Se você só fizer isso, nada vai acontecer. Primeiro você precisa incluir os arquivos. Você faz isso assim:
git add .
O “.” significa todos os arquivos do diretório abaixo do que você está. Se você está em um subdiretório e não quiser mudar, você pode fazer assim pra pegar todos os diretórios do repositório:
git add :/
Aí sim você faz o commit.
Quando você faz o add o Git coloca seus arquivos em uma área chamada de staging ou index. Ao comitar, somente o que está em staging vai pro commit. Outras alterações não vão. Eu uso muito o git add sempre que alcanço um marco interessante, de forma a poder comparar com o que eu fiz depois, usando “git diff”, já que esse comando me mostra a diferença entre o index e o diretório de trabalho. Quando alcanço um ponto significativo eu faço o commit. O Visual Studio esconde a existência do staging do desenvolvedor. Quem sabe com o tempo as pessoas se acostumam com o Git e o Visual Studio pára de escondê-lo.
Faça quantos commits você quiser. O importante é que eles tenham significado.
Algumas dicas:
- Não altere o que não diz respeito ao seu trabalho.
- Não toque em arquivos que não tem nada a ver com o que você está fazendo.
- Não reformate todo o código que outra pessoa escreveu.
- Respeite os padrões de nomes, formatação, etc.
- Leia a definição de pronto e verifique se você a atingiu.
- Não deixe espaços vazios no final das linhas.
Se você errou a mensagem de commit, faça um commit com amend:
git commit --amend -m "Nova mensagem"
Se você não usar o “-m” com a mensagem provavelmente o VIM vai abrir pra digitar. Não se desespere, e aproveite pra aprender alguma coisa sobre o VIM, é importante. O amend também permite que você acrescente mudanças que faltaram, basta incluir elas no staging antes de fazer o amend.
No Visual Studio o commit é feito no Team Explorer. Clique em Changes e as mudanças aparecem. Como eu disse, o staging não aparece:
Digite sua mensagem e clique em commit. Pra fazer o commit com amend, vá ao Team Explorer, e peça o histórico do Branch que você está:
Ele vai aparecer assim:
Dê um clique duplo sobre o último commit, ele vai aparecer no Team Explorer. Altere a mensagem e clique em “Amend Message”:
Se você acabou de fazer o commit pode clicar nele de imediato, no próprio Team Explorer, indo direto ao commit, sem precisar ir primeiro ao histórico.
Se você der refresh no histórico verá que o texto da mensagem e o seu sha (o id do commit) mudaram. O Visual Studio não permite incluir novas alterações, qualquer update nos arquivos feitos do commit não será considerado pelo amend. Pra isso você precisa fazer o amend na linha de comando.
No final você provavelmente fez vários commits. Mas não é uma boa ideia mandar 7 ou 8 commits no Pull Request, o ideal é mandar só um. Mas temos como resolver isso, no Git nada que ainda não foi empurrado está livre pra ser alterado, sejam commits, mensagens, tags, o que for.
Fazendo squash dos commits
No final você pode ser preocupar com a sua mensagem de commit. Aqui e aqui há boas recomendações pra uma boa mensagem de commit. Algumas regras são importantes, há uma convenção que é importante respeitar, ainda que não sejamos obrigados e tudo funcione sem elas:
- Mensagens sempre em inglês, o CodeCracker é feito por pessoas do mundo inteiro, elas precisam nos entender.
- Mensagem sempre separada em 2 seções, que ficam separadas por uma linha
- A primeira seção sempre começa com um verbo no imperativo e com letra maiúscula, por exemplo “Add NameOf Analyzer and Fix”. Ela não deve passar de 72 caracteres.
- A segunda seção tem número de linhas livre, mas não pode superar 72 caracteres em cada linha. Isso porque elas devem caber dentro de um terminal simples.
- Adicione o número da issue na descrição, usando os verbos “fix” ou “close”. Isso vai fechar o issue quando o Pull Request for aceito. Por exemplo:
”Closes #380
Also added a code fix provider and updated
extension methods.”
Se você só fez um commit, então fica fácil, faça um amend e corrija a mensagem, e você está pronto para ir em frente. Se você fez vários commits é importante juntá-los com o que chamos de “squash”. O squash vai pegar vários commits e juntar em um só. Só é possível fazer squash no terminal. Não se assuste, é simples. Antes de mais nada você vai fechar o Visual Studio. Se ele estiver aberto tudo pode falhar porque ele vai interferir nos arquivos. Em seguida você vai digitar no terminal:
git rebase -i master
Por exemplo, tenho esses 2 commits aqui:
Shas “b94” e “8fa”. Iniciando o comando de rebase aparecerá o editor padrão, normalmente o VIM, onde você pode escolher o que quer fazer. No meu caso uso o GVIM no Windows, porque o VIM não funciona muito bem no Powershell ou no Cmd. Aparece assim:
Estão sendo listados os 2 commits que foram feitos a partir do ponto onde está o master. É hora de juntá-los. Note que os comentários abaixo do texto já te dizem o que fazer. Queremos manter o primeiro commit (pick), mas fazer squash do segundo em diante:
Como fazer isso no VIM?
O vim separa o modo de inserção do modo de navegação no texto, chamado por ele de modo “normal”. Há outros modos mas isso não importa aqui. Você pode navegar no texto com hjkl ou com as setas do teclado. Na hora de inserir texto, aperte a tecla “i” (minúsculo). Digite a vontade, quando terminar aperte ESC. Pra sair e salvar aperte “:x”. Se der algo errado, aperte ESC várias vezes e depois aperte “u” (minúsculo) várias vezes, e ele irá desfazer tudo, e você pode começar de novo do zero. Pra cancelar tudo apague todas as linhas, salve e feche.
É possível que seu editor padrão seja o notepad, e aí vai aparecer tudo desformatado, porque o notepad não vai entender as quebras de linha fora do padrão Windows. Melhor usar o Sublime, o VIM, ou outro. Depois faço um post explicando como trocar o editor padrão.
Após fechar o editor você terá a opção de acertar a mensagem de commit. O git vai te mostrar todas as mensagens dos commits juntas, assim:
Acerte a mensagem, salve e feche. Tudo que estiver após “#” é um comentário.
Com isso o squash feito com o rebase conclui.
Após o rebase a linha de comando mostra o resultado:
Falta agora integrar com a master. Só temos um problema, o seu repositório local aponta como origem o seu github, não o oficial. Confira rodando “git remote -v”:
Você precisa acrescentar o oficial. Isso só precisa ser feito uma vez, na primeira vez que você for mandar o seu primeiro Pull Request. O Git permite ter mais de um remote. Faça isso com:
git remote add code-cracker https://github.com/code-cracker/code-cracker.git
Olhe só:
Agora você volta pro master, puxa o código que está no oficial e volta pro seu branch:
git checkout master git pull code-cracker master git checkout meu-branch
Quando você fizer o pull ele vai te mostrar se houveram novidades. Se hoveram ele mostra assim:
Note o “Updating…” e depois o “Fast-Forward”. Isso significa que houveram updates. E o fast-forward significa que o seu branch master local vai “andar” pra frente até encontrar o branch master do CodeCracker sem precisar de merge.
Se não houveram aparece assim:
Note o “Already up-to-date”.
Se não havia novidade no remote/master você já pode criar o pull request. Se houve, vamos fazer um rebase.
É muito provável que a master tenha recebido outros commits, de outros pull requests. Você vai precisar atualizar seus branches. Isso pode ser feito de mais de uma maneira, como veremos abaixo.
Fazendo Rebase
O rebase muda a base de uma linha de commits. Imagine que seu commit Y tem como pai o commit X, que era a antiga master. Mas houveram commits, a master andou, e agora a master está em Z. Algo assim:
O que vamos fazer é mudar a base do seu commit atual. Queremos que fique assim:
É parecido com um merge. A diferença é que um merge geraria um commit a mais, algo assim:
O rebase é muito melhor porque deixa uma linha limpa de commits.
O squash que fizemos antes já foi feito usando o comando rebase, mas o interativo, que permite fazer squash de commits, e até remover commits, ou reordená-los.
O que vamos fazer agora não precisa ser iterativo. Basta fazer o comando:
git checkout meu-branch git rebase master
Fica assim:
Também é possível fazer via Visual Studio. No Team Explorer/Branches, clique com o botão direito no seu branch e selecione “Rebase Onto…”:
Selecione master nas opções:
E clique em rebase.
Não faça rebase pela linha de comando com o Visual Studio aberto, pode dar problemas.
Durante o rebase, o que está acontecendo é que o Git está desfazendo seus commits até chegar no primeiro ponto de intersecção entre o seu branch e os commits da master, andando então até a ponta da master, e então aplicando novamente seus commits, que estavam guardados. Mas podem acontecer problemas, tanto fazendo pelo Visual Studio quanto na linha de comando, devido a conflitos. Você pode ter alterado a mesma linha de um arquivo que outra pessoa alterou. É igual a um conflito de merge. Você resolve e segue em frente. Se tudo falhar, você sempre pode cancelar tudo, rodando:
git rebase --abort
Esse abort vai fazer com que tudo esteja exatamente como antes do começo do rebase.
No meio do conflito você vai corrigindo, rodando git add nos arquivos que estão ok, e no final você faz:
git rebase --continue
Não é algo complexo, mas sugiro você brincar com a ideia em um repositório de testes pra ficar confortável. Quando eu estava aprendendo, o que eu fazia antes de fazer qualquer squash ou rebase era fazer um clone ou uma cópia do diretório do projeto, em caso de qualquer problema eu tinha um backup. Hoje não preciso mais fazer isso, mas ajudou muito quando eu estava aprendendo e me libertou para poder quebrar tudo sem medo. E algumas vezes eu quebrei mesmo. 🙂
Criando o Pull Request
Com o squash feito você já pode enviar seu código pro Github. Basta fazer um push, assim:
git push -u origin meu-branch
Você só precisa do “-u” no primeiro push. Nos seguintes você pode fazer só “git push”. Ele serve pra dizer que o seu branch local está acompanhando o branch remoto apontado.
Se você já tinha feito push antes do rebase o Github vai rejeitar seu push. Você precisará enviar um push forçado, assim:
git push --force
CUIDADO! Push forçado pode destruir tudo. Tenha certeza do que está fazendo, rode um “git status” antes.
Quando você faz um git push pro Github e navega pro seu repositório em seguida, ele te sugere criar um Pull Request. Vejam o exemplo:
Aí é só seguir com o Pull Request no Github. Não esqueça de informar o número da issue no corpo do Github, por exemplo ”closes #1000”.
Com o PR criado agora é só acompanhar. O primeiro feedback que você vai ter é se a build no AppVeyor passou. Essa build vai compilar tudo e rodar os testes. Se passou, ela vai subir o relatório de cobertura de código pro Coveralls. Lá você vai poder ver se deixou de testar alguma coisa. Você também pode ver essa cobertura localmente rodando o arquivo “.\test.ps1” e verificando o diretório “log”, ou usando o Visual Studio. Se a build falhou ou a cobertura de código caiu muito, verifique o que houve.
Em seguida você terá feedback dos mantenedores do projeto, Carlos, Elemar ou eu. Se encontrarmos algum problema vamos te pedir pra atualizar o código. Isso é normal, acontece em quase todo PR. Discuta o que precisa ser melhorado e se prepare para atualizar.
Se precisar atualizar, refaça processo todo, faça seu commit, squash, rebase e push force. Quando fizer o push pro seu repo o PR vai atualizar sozinho e vai iniciar uma nova build. Avise no PR que você atualizou o código e que fez rebase, pra que quem estiver verificando possa continuar.
Em tempo o seu PR entra, e você se torna mais um contribuidor do projeto! Já temos mais de 20! Esperamos contar com a sua contribuição.
Iniciando um novo trabalho
Se você resolver pegar outro issue pra trabalhar, sempre se lembre de atualizar o master com o repositório oficial do CodeCracker, pra não ter grandes conflitos no rebase mais tarde. Sempre rode antes de começar:
git checkout master git pull code-cracker master
Observação: Além da linha e comando e ocasionamente o Visual Studio também uso o gitk e o git gui, além do próprio VIM com a extensão fugitive. Investigue se te interessa.
Giovanni Bassi
Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.