Enviando código

Esta seção é destinada para os committers e para qualquer interessado em entender como o código é comitado no Django. Se você é membro de uma comunidade e quer contribuir com código para o Django, veja o Trabalhando com Git e GitHub.

Manipulando pull requests

Como o Django agora é hospedado no GitHub, a maioria das melhorias é fornecida na forma de pull requests.

Ao fazer um pull request, certifique-se de que cada commit individualmente satisfaça as regras descritas abaixo. Espera-se de quem contribui os melhores pull requests possíveis de se fornecer. Na prática, entretanto, os committers, - quem provavelmente estará mais familiarizado com as regras do projeto - podem decidir melhorar a qualidade de um commit por conta própria.

Você pode querer ter o Jenkins a testar o pull request com um dos pull requests builders que não rodem automaticamente, como o Oracle or Selenium. Veja a página wiki do Jenkins para mais instruções

Um jeito fácil de fazer checkout de um pull request localmente é adicionando um alias no seu ~/.gitconfig (estamos assumindo que django/django é o nosso upstream):

[alias]
    pr = !sh -c \"git fetch upstream pull/${1}/head:pr/${1} && git checkout pr/${1}\"

Agora você pode simplesmente executar git pr #### para realizar o checkout do pull request correspondente.

A partir deste momento, você pode trabalhar no código. Utilize git rebase -i e git commit --amend para garantir que os commits tenham o nível de qualidade desejado. Quando você estiver pronto:

$ # Pull in the latest changes from master.
$ git checkout master
$ git pull upstream master
$ # Rebase the pull request on master.
$ git checkout pr/####
$ git rebase master
$ git checkout master
$ # Merge the work as "fast-forward" to master to avoid a merge commit.
$ # (in practice, you can omit "--ff-only" since you just rebased)
$ git merge --ff-only pr/XXXX
$ # If you're not sure if you did things correctly, check that only the
$ # changes you expect will be pushed to upstream.
$ git push --dry-run upstream master
$ # Push!
$ git push upstream master
$ # Delete the pull request branch.
$ git branch -d pr/xxxx
...\> REM Pull in the latest changes from master.
...\> git checkout master
...\> git pull upstream master
...\> REM Rebase the pull request on master.
...\> git checkout pr/####
...\> git rebase master
...\> git checkout master
...\> REM Merge the work as "fast-forward" to master to avoid a merge commit.
...\> REM (in practice, you can omit "--ff-only" since you just rebased)
...\> git merge --ff-only pr/XXXX
...\> REM If you're not sure if you did things correctly, check that only the
...\> REM changes you expect will be pushed to upstream.
...\> git push --dry-run upstream master
...\> REM Push!
...\> git push upstream master
...\> REM Delete the pull request branch.
...\> git branch -d pr/xxxx

Force push to the branch after rebasing on master but before merging and pushing to upstream. This allows the commit hashes on master and the branch to match which automatically closes the pull request.

If a pull request doesn’t need to be merged as multiple commits, you can use GitHub’s “Squash and merge” button on the website. Edit the commit message as needed to conform to the guidelines and remove the pull request number that’s automatically appended to the message’s first line.

Quando estiver reescrevendo o histórico de commits de um pull request, o objetivo é fazer com que o histórico de commits do Django seja o mais útil possível:

  • Se um patch possui retornos e avanços nos commits, então reescreva esses em um só. Por exemplo, se um commit adiciona mais código e um segundo commit faz ajustes em problemas de estilo introduzidos pelo primeiro commit, esses commits devem ser unificados antes de se fazer um merge.
  • Separe as mudanças em diferentes commits por grupos lógicos: se você faz uma limpeza de estilo ao mesmo tempo em que você faz outras mudanças em um arquivo, a separação dessas mudanças em dois commits diferentes fará a revisão do histórico de alterações mais simples.
  • Cuidado com merges de branches do upstream dentro de pull requests.
  • Testes devem passar e a documentação deve ser gerada depois de cada commit. Nem os testes, nem a documentação devem emitir avisos.
  • Patchs triviais e pequenos costumam ser melhor realizados em um único commit. Trabalhos médios ou maiores podem ser quebrados em múltiplos commits se isso fizer sentido.

Praticidade vence pureza, então cabe a cada committer decidir o quanto refinar o histórico antes de um pull request. O principal é engajar a comunidade, terminar o trabalho, e ter um histórico de commits utilizável.

Regras de commit

Adicionalmente, por favor siga as regras a seguir quando estiver commitando código para o repositório do Django no git:

  • Nunca altere o histórico publicado dos “branches” do django/django através de um “push” forçado. Se for absolutamente necessário (por razões de segurança), primeiro discuta a situação com o time.

  • Para qualquer mudança de média para grande, onde “média para grande” é de acordo com o seu próprio julgamento, por favor traga o problema para a lista de e-mail django-developers antes de fazer a mudança.

    If you bring something up on django-developers and nobody responds, please don’t take that to mean your idea is great and should be implemented immediately because nobody contested it. Everyone doesn’t always have a lot of time to read mailing list discussions immediately, so you may have to wait a couple of days before getting a response.

  • Escreva os commits com mensagens detalhadas e utilizando o passado como tempo verbal, não o presente.

    • Bom: “Corrigido bug de Unicode na API de RSS.”
    • Ruim: “Corrige bug de Unicode na API de RSS.”
    • Ruim: “Corrigindo bug de Unicode na API de RSS.”

    The commit message should be in lines of 72 chars maximum. There should be a subject line, separated by a blank line and then paragraphs of 72 char lines. The limits are soft. For the subject line, shorter is better. In the body of the commit message more detail is better than less:

    Fixed #18307 -- Added git workflow guidelines.
    
    Refactored the Django's documentation to remove mentions of SVN
    specific tasks. Added guidelines of how to use Git, GitHub, and
    how to use pull request together with Trac instead.
    

    Se o patch não foi um pull request, você deverá dar crédito as pessoas que contribuiram na mensagem de commit: “Obrigado A por avisar, B pelo patch e C por revisar.”

  • Para commits em uma branch, coloque antes da mensagem de commit o nome da branch. Por exemplo: “[1.4.x] Fixed #xxxxx – Adicionado suporte para leitura de mentes.”

  • Limit commits to the most granular change that makes sense. This means, use frequent small commits rather than infrequent large commits. For example, if implementing feature X requires a small change to library Y, first commit the change to library Y, then commit feature X in a separate commit. This goes a long way in helping everyone follow your changes.

  • Separate bug fixes from feature changes. Bugfixes may need to be backported to the stable branch, according to Versões suportadas.

  • Se o seu commit fecha um ticket no rastreador de tickets do Django, comece a sua mensagem de commit com o texto “Fixed #xxxxx”, onde “xxxxx” é o número do ticket que o seu commit corrige. Exemplo: “Corrigido #123 – Adicionada a funcionalidade whizbang.”. Nós configuramos o Trac de modo que qualquer mensagem de commit nesse formato irá automaticamente fechar o ticket referenciado e colocar um comentário nele com a mensagem completa do commit.

    Para os curiosos, nós estamos utilizando um plugin do Track para isso.

Nota

Repare que a integração com o Trac não sabe nada sobre os pull requests. Portanto, se você tentar fechar um pull request com a frase “encerra #400 na sua mensagem de commit, o GitHub irá fechar o pull request, mas o plugin do Trac irá fechar também o respectivo ticket dentro do Trac.

  • Se o seu commit faz referência a um ticket no rastreador de tickets do Django mas não fecha o ticket, inclua a frase “Refs #xxxxx”, onde “xxxxx” é o número do ticket que o seu commit faz menção. Isso irá automaticamente postar um comentário na página do respectivo ticket.

  • Write commit messages for backports using this pattern:

    [<Django version>] Fixed <ticket> -- <description>
    
    Backport of <revision> from <branch>.
    

    Por exemplo:

    [1.3.x] Fixed #17028 -- Changed diveintopython.org -> diveintopython.net.
    
    Backport of 80c0cbf1c97047daed2c5b41b296bbc56fe1d7e3 from master.
    

    Existe um script na wiki para automatizar isso.

    If the commit fixes a regression, include this in the commit message:

    Regression in 6ecccad711b52f9273b1acb07a57d3f806e93928.
    

    (use the commit hash where the regression was introduced).

Revertendo commits

Ninguém é perfeito; erros serão comitados.

Mas esforce-se de verdade para garantir que erros não aconteçam. O fato de termos uma política de reversão não reduz a sua responsabilidade em buscar o maior padrão de qualidade possível. De verdade: revise o seu trabalho duas vezes, ou deixe ele ser revisado por outro committer, antes de você já ter feito o commit dele!

Quando um commit indevido é descoberto, por favor siga as instruções abaixo:

  • Se possível, deixe que o autor original reverta o seu próprio commit.
  • Não faça o revert das mudanças de outro autor sem a permissão do autor original.
  • Utilize o git revert – isso irá fazer um commit reverso, mas o commit original ainda será parte do histórico de commits.
  • Se o autor original não puder ser encontrado (dentro de um prazo razoável – um dia ou algo assim) e o problema é severo – bug quebrando a build, vários testes falhando, etc. – então pergunte se existe alguma objeção na lista de e-mail django-developers e então reverta o código se elas não existirem.
  • Se o problema é pequeno (uma funcionalidade congelada, por exemplo) aguarde.
  • Se existir um desacordo entre o committer e o autor do código a sofrer um revert então tente solucionar o problema na lista de e-mail django-developers. Se um acordo não puder ser encontrado então o problema deve ser submetido a uma votação.
  • Se o commit introduziu uma vulnerabilidade de segurança confirmada, aberta então o commit deve ser revertido imediatamente sem permissão de ninguém.
  • O mantenedor da branch de releases pode voltar commits nessa branch sem permissão caso o commit tenha quebrado a branch de releases.
  • Se você erroneamente fizer um “push” em um “branch” para “django/django”, apenas delete. Por exemplo, se você fizer git push upstream feature_antigravity, apenas reverta o “push”: git push upstream :feature_antigravity.
Back to Top