Trabalhando com Git e GitHub

Esta seção explica como a comunidade pode contribuir com código para o Django via pull requests. Se você está interessado em como os core developers manipulam eles, veja Enviando código.

Abaixo, nós vamos mostrar como criar um pull request no GitHub contendo as mudanças para o ticket #xxxxx do Trac. Criando um pull request totalmente pronto você irá facilitar o trabalho do revisor, significando que o seu trabalho tem maiores chances de ser mesclado dentro do Django.

Você também poderia fazer upload de um patch tradicional no Trac, mas isso é menos prático para os revisores.

Instalando Git

O Django utiliza Git para o seu versionamento código. Você pode baixá-lo em , mas costuma ser mais simples instalá-lo usando o gerenciador de pacotes do seu sistema operacional.

O repositório do Django é hospedado no GitHub, e é recomendado que você também trabalhe usando o GitHub.

Depois de instalar o Git a primeira coisa que você deve fazer é configurar o seu nome e e-mail:

$ git config --global user.name "Your Real Name"
$ git config --global user.email "you@email.com"

Note que user.name deve ser o seu nome real, e não o seu nick no GitHub. O GitHub deve saber o email que você usa pelo campo user.email, já que ele será usado para associar os seus commits com a sua conta no GitHub.

Configurando o repositório local

Uma vez que você tenha criado a sua conta no GitHub, com o nick “GitHub_nick”, e realizado o fork do repositório do Django, crie uma cópia local do seu fork:

git clone git@github.com:GitHub_nick/django.git

Isso irá criar um novo diretório “django”, contendo um clone do seu repositório no GitHub. O resto dos comandos nesta página precisam ser executados dentro do diretório clonado então mude para ele agora:

cd django

O seu repositório GitHub será chamado de “origin” no Git.

Você também deverá configurar django/django como sendo um “upstream” remoto (isto é, diga ao git que a referência ao repositório do Django era a fonte do seu fork):

git remote add upstream git@github.com:django/django.git
git fetch upstream

Você pode adicionar outros “upstreams” remotos de modo similar, por exemplo:

git remote add akaariai git@github.com:akaariai/django.git

Trabalhando em um ticket

Quando estiver trabalhando em um ticket crie uma nova branch para ele, e utilize como base o upstream/master:

git checkout -b ticket_xxxxx upstream/master

A flag -b cria uma nova branch para você localmente. Não hesite em criar novas branches mesmo para as coisas mais simples - esse é o motivo delas existirem.

Se ao invés disso você estiver trabalhando em uma correção na branch 1.4, você poderia fazer:

git checkout -b ticket_xxxxx_1_4 upstream/stable/1.4.x

Assumindo que o trabalho está sendo realizado na branch ticket_xxxxx. Altere algumas mudanças e faça o commit delas:

git commit

Quando estiver escrevendo uma mensagem de commit, siga as orientações para mensagens de commit para facilitar o trabalho do committer. Se você estiver desconfortável em usar inglês, tente pelo menos descrever precisamente o que o commit faz.

Se você precisar fazer trabalho adicional na sua branch, faça commit com tanta frequência quanto for necessário.

git commit -m 'Added two more tests for edge cases'

Publicando trabalho

Você pode publicar o seu trabalho no GitHub fazendo o seguinte:

git push origin ticket_xxxxx

Quando você for para a sua página no GitHub você irá reparar que uma nova branch foi criada.

Se você está trabalhando em um ticket do Trac, você deve mencionar no ticket que o seu trabalho está disponível através da branch ticket_xxxxx do seu repositório no GitHub. Inclua um link para a sua branch.

Tenha em mente que a branch acima é chamada de “topic branch” no linguajar do Git. Você é livre para reescrever o histórico dessa branch, através do uso do git rebase por exemplo. Outras pessoas não deveriam basear o seu trabalho em uma branch como essa, porque os clones dela serão corrompidos quando você editar os seus commits.

Existem também “branches públicas”. Essas são branches das quais espera-se que outras pessoas façam seus forks, então o histórico dessas branches não deve nunca ser mudado. Bons exemplos de branches públicas são a master e a stable/A.B.x no repositório do django/django.

Quando você achar que o seu trabalho está pronto para ser enviado para o Django, você deve criar um pull request no GitHub. Um bom pull request significa:

  • Commits com uma mudança lógica, seguindo o estilo de código,

  • Mensagens bem formatadas para cada commit: uma linha de sumário e então parágrafos embutidos em até 72 caracteres depois dela – veja as regras de commit para mais detalhes.

  • Documentação e testes, quando necessário – na verdade testes são sempre necessários, exceto para mudanças na documentação.

A suíte de testes deve passar e a documentação deve ser gerada sem quaisquer warnings.

Uma vez que você tenha criado o seu pull request, você deve adicionar um comentário no respectivo ticket do Trac explicando o que você fez. Em particular você deve descrever o ambiente no qual você rodou os testes, por exemplo: “todos os testes passam para o SQLite e MySQL”.

Pull Requests no GitHub só possuem dois estados: aberto e fechado. O committer que for lidar com o seu pull request só tem duas opções: fazer merge dele ou fechá-lo. Por esta razão, não é útil fazer um pull request enquanto o código não estiver pronto para o merging – ou suficientemente concluído a ponto de o próprio committer finalizá-lo ele mesmo.

Fazendo rebase de branches

No exemplo acima você criou dois commits, o commit “Fixed ticket_xxxxx” – “Corrigido ticket_xxxxx” – e o commit “Added two more tests” – “Adicionado mais dois testes”.

Nós não queremos ter o histórico inteiro do seu processo de trabalho no seu repositório. O seu commit “Added two more tests” seria poluído e pouco amigável. Ao invés disso, nós preferimos ter apenas um commit contendo todo o seu trabalho.

Para retrabalhar o histórico da sua branch você pode esmagar os commits tornando todos eles uma coisa só através do uso interativo do rebase:

git rebase -i HEAD~2

O HEAD~2 acima é um atalho para os dois últimos commits. O comando acima irá abrir um editor mostrando os dois commits, prefixados com a palavra “pick”.

Mude “pick” na segunda linha para “squash”. Isso manterá o primeiro commit, e esmagará o segundo commit dentro do primeiro. Salve e feche o editor. Uma segunda janela do editor deverá abrir, de modo que você possa reescrever a mensagem de commit agora que ele está incluindo os seus dois passos.

Você também pode usar a opção “edit” no rebase. Desta forma você pode mudar um único commit, por exemplo para corrigir um erro de ortografia em uma docstring:

git rebase -i HEAD~3
# Choose edit, pick, pick for the commits
# Now you are able to rework the commit (use git add normally to add changes)
# When finished, commit work with "--amend" and continue
git commit --amend
# reword the commit message if needed
git rebase --continue
# The second and third commits should be applied.

Se a sua topic branch já está publicada no GitHub, por exemplo se você está fazendo pequenas mudanças para levar em consideração uma revisão, você precisará forçar o push das mudanças.

git push -f origin ticket_xxxxx

Repare que isso irá reescrever o histórico do ticket_xxxxx - se você verificar os hashes dos commits antes e depois dessa operação no GitHub você vai perceber que eles não coincidem mais. Isso é aceitável já que o branch é meramente um topic branch e ninguém deveria estar trabalhando baseando o seu trabalho nele.

Depois que o upstream foi modificado

Quando o upstream (django/django) é modificado, você deverá executar o comando rebase no seu trabalho. Para isso faça o seguinte:

git fetch upstream
git rebase

O trabalho é automaticamente rebaseado usando a branch da qual você fez o branch. No nosso exemplo usando upstream/master.

O comando rebase remove todos os seus commits locais temporariamente, aplica os commits do upstream, e então aplica os seus commits locais novamente.

Se existirem conflitos de merge você terá que resolvê-los e então usar git rebase --continue. A qualquer momento você pode usar git rebase --abort para retornar ao estado original.

Note que você quer fazer rebase no upstream, e não merge do upstream.

A razão para isso é que ao fazer o rebase, os seus commits sempre ficarão no topo do trabalho realizado no upstream e não misturado com as mudanças do upstream. Desta forma a sua topic branch irá conter somente commits relacionados a ela, o que faz com que o processo de esmagar os seus commits fique mais simples.

Depois de revisar

É muito incomum receber qualquer porção de código não trivial incluída no core do Django sem quaisquer alterações sendo solicitadas pelos revisores. Neste caso, costuma ser uma boa ideia adicionar as mudanças na forma de um commit incremental para o seu trabalho. Isso permite que os revisores possam checar facilmente quais mudanças você fez.

Neste caso, faça as mudanças solicitadas pelo revisor. Faça commit tão frequentemente quanto necessário. Antes de publicar as mudanças, faça o rebase do seu trabalho. Se você adicionou mais dois commits, você pode rodar o seguinte comando:

git rebase -i HEAD~2

Esmague o segundo commit dentro do primeiro. Escreva uma mensagem de commit junto das linhas de:

Made changes asked in review by <reviewer>

- Fixed whitespace errors in foobar
- Reworded the docstring of bar()

Finalmente faça o push do seu trabalho de volta para o repositório do GitHub. Já que você não tocou nos commits públicos durante o rebase, você não deve precisar forçar um push:

git push origin ticket_xxxxx

O seu pull request deve agora conter um novo commit também.

Note que o committer provavelmente irá esmagar o commit revisado dentro de outros commits prévios quando estiver fazendo a submissão do código.

Trabalhando em um patch

Uma das formas que os desenvolvedores podem contribuir com o Django é revisando patches. Esses patches tipicamente existirão na forma de pull requests no GitHub e poderão ser facilmente integrados dentro do seu repositório local:

git checkout -b pull_xxxxx upstream/master
curl https://github.com/django/django/pull/xxxxx.patch | git am

Isso irá criar uma nova branch e então aplicar as mudanças do pull request nela. Neste momento você pode rodar os testes ou fazer qualquer coisa que você precise para investigar a qualidade do patch.

Para mais detalhes sobre como trabalhar com pull requests veja as orientações para committers.

Resumo

  • Trabalhe no GitHub se você puder.

  • Anuncie o seu trabalho no ticket do Trac adicionando um link para a sua branch no GitHub.

  • Quando você tiver algo pronto, faça um pull request.

  • Faça os melhores pull requests que você puder fazer.

  • Quando estiver fazendo correçṍes para o seu trabalho, use git rebase -i para esmagar os commits.

  • Quando o upstream tiver sido alterado, faça git fetch upstream; git rebase.

Back to Top