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:

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:

image

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:

image

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.

image

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”:

image

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:

image

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:

image

Clique em Branches, ficará parecido com isso:

image

Clique com botão direito no branch master e selecione “New Local Branch from…”, e dê um nome pro seu branch:

image

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:

image

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:

image

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á:

image

Ele vai aparecer assim:

image

Dê um clique duplo sobre o último commit, ele vai aparecer no Team Explorer. Altere a mensagem e clique em “Amend Message”:

image

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:

image

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:

image

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:

image

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:

image

Acerte a mensagem, salve e feche. Tudo que estiver após “#” é um comentário.

image

Com isso o squash feito com o rebase conclui.

Após o rebase a linha de comando mostra o resultado:

image

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”:

image

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ó:

image

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:

image

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:

image

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:

image

O que vamos fazer é mudar a base do seu commit atual. Queremos que fique assim:

image

É parecido com um merge. A diferença é que um merge geraria um commit a mais, algo assim:

image

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:

image

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…”:

image

Selecione master nas opções:

image

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:

image

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”.

image

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.