{"title":"提交代码","version":"6.0","locale":"zh-hans","docname":"internals/contributing/committing-code","url":"/zh-hans/6.0/internals/contributing/committing-code/","canonical":"https://djangodocs.dev/zh-hans/6.0/internals/contributing/committing-code/","summary":"This section is addressed to the mergers and to anyone interested in knowing how code gets committed into Django. The 提交指南 apply to all contributors, with or…","html":"<h1>提交代码<a class=\"heading-anchor\" href=\"#committing-code\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h1>\n<p>This section is addressed to the mergers and to anyone interested in knowing\nhow code gets committed into Django. The <a class=\"reference internal\" href=\"#committing-guidelines\"><span class=\"std std-ref\">提交指南</span></a> apply\nto all contributors, with or without commit rights.</p>\n<p>如果您是想向 Django 贡献代码的社区成员，请前往查看 <a class=\"reference internal\" href=\"/zh-hans/6.0/internals/contributing/writing-code/working-with-git/\"><span class=\"doc\">使用 Git 和 GitHub 工作</span></a>。</p>\n<section id=\"handling-pull-requests\">\n<span id=\"id1\"></span><h2>处理 pull 请求<a class=\"heading-anchor\" href=\"#handling-pull-requests\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>因为Django现在是托管在GitHub上的，所以大多数补丁都是以 pull requests 的形式提供的。</p>\n<p>提交拉取请求时，请确保每个单独的提交符合下面描述的提交准则。我们期望贡献者提供最好的拉取请求。在实践中，合并者（很可能更熟悉提交准则）可能会决定自行将提交符合标准。</p>\n<p>你可能希望使用 Jenkins 或 GitHub actions 来测试拉取请求，其中之一是不会自动运行的拉取请求构建器，比如 Oracle 或 Selenium。请查看 <a class=\"reference external\" href=\"https://code.djangoproject.com/wiki/CI\">CI wiki 页面</a> 获取说明。</p>\n<p>如果您发现自己经常在本地检出拉取请求，这个 Git 别名将会很有帮助：</p>\n<div class=\"code-block\" data-language=\"ini\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Ini</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Ini code\"><code><span class=\"k\">[alias]</span>\n<span class=\"w\">    </span><span class=\"na\">pr</span><span class=\"w\"> </span><span class=\"o\">=</span><span class=\"w\"> </span><span class=\"s\">!sh -c \\&quot;git fetch upstream pull/${1}/head:pr/${1} &amp;&amp; git checkout pr/${1}\\&quot;</span>\n</code></pre></div>\n<p>将它添加到你的 <code class=\"docutils literal notranslate\"><span class=\"pre\">~/.gitconfig</span></code> 文件中，并且把 <code class=\"docutils literal notranslate\"><span class=\"pre\">upstream</span></code> 改为 <code class=\"docutils literal notranslate\"><span class=\"pre\">django/django</span></code> 。然后你就可以通过运行 <code class=\"docutils literal notranslate\"><span class=\"pre\">git</span> <span class=\"pre\">pr</span> <span class=\"pre\">####</span></code> 来检出对应的 pull request 了。</p>\n<p>到了这个阶段,你可以着手于代码.使用&quot;git rebase -i&quot;和&quot;git commit --ammend&quot; 来确保你的提交准确无误. 一旦你准备好了:</p>\n<div class=\"console\" data-console><div class=\"console-panel\" data-platform=\"unix\"><p class=\"console-label\" id=\"console-0-unix-label\">Linux / macOS</p><div class=\"code-block\" data-language=\"console\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Shell</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Shell code\"><code><span class=\"gp\">$ </span><span class=\"c1\"># Pull in the latest changes from main.</span>\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>checkout<span class=\"w\"> </span>main\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>pull<span class=\"w\"> </span>upstream<span class=\"w\"> </span>main\n<span class=\"gp\">$ </span><span class=\"c1\"># Rebase the pull request on main.</span>\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>checkout<span class=\"w\"> </span>pr/####\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>rebase<span class=\"w\"> </span>main\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>checkout<span class=\"w\"> </span>main\n<span class=\"gp\">$ </span><span class=\"c1\"># Merge the work as &quot;fast-forward&quot; to main to avoid a merge commit.</span>\n<span class=\"gp\">$ </span><span class=\"c1\"># (in practice, you can omit &quot;--ff-only&quot; since you just rebased)</span>\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>merge<span class=\"w\"> </span>--ff-only<span class=\"w\"> </span>pr/XXXX\n<span class=\"gp\">$ </span><span class=\"c1\"># If you&#39;re not sure if you did things correctly, check that only the</span>\n<span class=\"gp\">$ </span><span class=\"c1\"># changes you expect will be pushed to upstream.</span>\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>push<span class=\"w\"> </span>--dry-run<span class=\"w\"> </span>upstream<span class=\"w\"> </span>main\n<span class=\"gp\">$ </span><span class=\"c1\"># Push!</span>\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>push<span class=\"w\"> </span>upstream<span class=\"w\"> </span>main\n<span class=\"gp\">$ </span><span class=\"c1\"># Delete the pull request branch.</span>\n<span class=\"gp\">$ </span>git<span class=\"w\"> </span>branch<span class=\"w\"> </span>-d<span class=\"w\"> </span>pr/xxxx\n</code></pre></div>\n</div><div class=\"console-panel\" data-platform=\"windows\"><p class=\"console-label\" id=\"console-0-windows-label\">Windows</p><div class=\"code-block\" data-language=\"doscon\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">Windows</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"Windows shell\"><code><span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM Pull in the latest changes from main.</span>\n<span class=\"gp\">...\\&gt;</span> git checkout main\n<span class=\"gp\">...\\&gt;</span> git pull upstream main\n<span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM Rebase the pull request on main.</span>\n<span class=\"gp\">...\\&gt;</span> git checkout pr/####\n<span class=\"gp\">...\\&gt;</span> git rebase main\n<span class=\"gp\">...\\&gt;</span> git checkout main\n<span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM Merge the work as &quot;fast-forward&quot; to main to avoid a merge commit.</span>\n<span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM (in practice, you can omit &quot;--ff-only&quot; since you just rebased)</span>\n<span class=\"gp\">...\\&gt;</span> git merge --ff-only pr/XXXX\n<span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM If you&#39;re not sure if you did things correctly, check that only the</span>\n<span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM changes you expect will be pushed to upstream.</span>\n<span class=\"gp\">...\\&gt;</span> git push --dry-run upstream main\n<span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM Push!</span>\n<span class=\"gp\">...\\&gt;</span> git push upstream main\n<span class=\"gp\">...\\&gt;</span> <span class=\"c1\">REM Delete the pull request branch.</span>\n<span class=\"gp\">...\\&gt;</span> git branch -d pr/xxxx\n</code></pre></div></div></div>\n<p>在将主分支重新基于重置后、合并并推送到上游之前，强制推送到分支。这样可以使主分支和分支上的提交哈希匹配，自动关闭拉取请求。</p>\n<p>如果拉请求不需要合并为多个提交，则可以在网页上使用 Github 的“Squash and merge”按钮。根据需要编辑提交消息以符合 <a class=\"reference internal\" href=\"#committing-guidelines\"><span class=\"std std-ref\">指南</span></a> 并删除自动附加到消息第一行的请求编号。</p>\n<p>当重写pull请求的提交历史时，目标是使Django的提交历史尽可能可用：</p>\n<ul class=\"simple\">\n<li><p>如果补丁包含来回提交，则将其重写为一个。例如，如果提交添加了一些代码，第二个提交修复了第一次提交中引入的样式问题，那么这些提交应该在合并之前被压缩。</p></li>\n<li><p>通过逻辑分组对不同提交进行单独更改：如果在对文件进行其他更改的同时进行样式清理，则将更改分成两个不同的提交将使查看历史记录变得更容易。</p></li>\n<li><p>注意拉取请求中上游分支的合并。</p></li>\n<li><p>测试应该通过，文档应该在每次提交后构建。测试和文档都不应该发出警告。</p></li>\n<li><p>随意和小型的补丁通常最好在一次提交中完成。如果有意义，可以将中型到大型工作分成多个提交。</p></li>\n</ul>\n<p>实用性胜过纯粹性，因此由每个合并者决定拉取请求的历史重塑程度。主要目标是与社区互动、完成工作并拥有可用的提交历史。</p>\n</section>\n<section id=\"committing-guidelines\">\n<span id=\"id2\"></span><h2>提交指南<a class=\"heading-anchor\" href=\"#committing-guidelines\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>These guidelines apply to all commits to Django's Git repository, whether\nsubmitted by a contributor via a pull request or landed directly by a merger:</p>\n<ul>\n<li><p>永远不要通过强制推动来改变“django / django``分支的已发布历史。如果您绝对必须（出于安全原因），请先与团队讨论情况。</p></li>\n<li><p>For any medium-to-big changes, where &quot;medium-to-big&quot; is according to\nyour judgment, please bring things up on the <a class=\"reference external\" href=\"https://forum.djangoproject.com/\">Django Forum</a> before making\nthe change.</p>\n<p>If you bring something up and nobody responds, please don't take that\nto mean your idea is great and should be implemented immediately because\nnobody contested it. Everyone doesn't always have a lot of time to read\ndiscussions immediately, so you may have to wait a couple of days before\ngetting a response.</p>\n</li>\n<li><p>Write detailed commit messages in the past tense, not present tense, and\nend the subject line with a period.</p>\n<ul class=\"simple\">\n<li><p>正确：&quot;Fixed Unicode bug in RSS API.&quot;</p></li>\n<li><p>错误：&quot;Fixes Unicode bug in RSS API.&quot;（用了现在时）</p></li>\n<li><p>错误：&quot;Fixing Unicode bug in RSS API.&quot;（用了&quot;-ing&quot;形式）</p></li>\n<li><p>错误：&quot;Fixed Unicode bug in RSS API&quot;（缺句号）</p></li>\n</ul>\n<p>提交消息最多应为72个字符。 应该有一个主题行，用空白行分隔，然后是72个字符行的段落。 限制很松。 对于主题行，越短越好。 在提交消息的主体中，更多细节优于更少。</p>\n<p>In the body of the commit message more detail is better than less, and should\nexplain <em>why</em> the change was made, not <em>what</em> was changed or <em>how</em>. The code\nitself shows what changed; the commit message should provide the context and\nreasoning that the code cannot.</p>\n<p>Credit the contributors in the commit message: &quot;Thanks A for the report and B\nfor review.&quot; Use git's <a class=\"reference external\" href=\"https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/creating-a-commit-with-multiple-authors\">Co-Authored-By</a> as appropriate, including anyone\nwhose earlier work the change builds on.</p>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"none\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">None</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"None code\"><code>Fixed #18307 -- Added git workflow guidelines.\n\nRefactored the Django&#39;s documentation to remove mentions of SVN\nspecific tasks. Added guidelines of how to use Git, GitHub, and\nhow to use pull request together with Trac instead.\n\nThanks to Full Name for the report, and to Reviewer for reviews.\n</code></pre></div>\n</li>\n<li><p>对于提交到分支，请在提交消息前面加上分支名称。例如：“[1.4.x]Fixed XXXX——增加了对思维阅读的支持。”</p></li>\n<li><p>限制承诺最细微的变化是有意义的。这意味着，使用频繁的小额承诺，而不是很少的大额承诺。例如，如果实现功能X需要对库Y做一个小的更改，那么首先将更改提交到库Y，然后在单独的提交中提交功能X。这对帮助每个人跟踪你的变化有很大的帮助。</p></li>\n<li><p>将错误修复与功能更改分开。根据 <a class=\"reference internal\" href=\"/zh-hans/6.0/internals/release-process/#supported-versions-policy\"><span class=\"std std-ref\">支持的版本</span></a>，可能需要将错误修复返回到稳定分支。</p></li>\n<li><p>如果你的提交解决了 Django <a class=\"reference external\" href=\"https://code.djangoproject.com/\">ticket tracker</a> 中的一个 ticket，请在提交信息的开头添加 &quot;Fixed #xxxxx&quot;，其中 ”xxxxx&quot; 是你提交所解决的 ticket 的编号。示例：&quot;Fixed #123 -- Added whizbang feature.&quot; 。当系统检测到这种提交信息格式时，系统会自动关闭所指向的 ticket 并将完整的提交信息作为评论发出。</p>\n<p>如果你好奇的话，我们使用 <a class=\"reference external\" href=\"https://github.com/trac-hacks/trac-github\">Trac plugin</a> 来实现这种机制。</p>\n</li>\n</ul>\n<aside class=\"admonition admonition-note\" role=\"note\">\n<p class=\"admonition-title\">Note</p>\n<p>请注意，Trac 集成对拉取请求一无所知。因此，如果你在提交信息中使用了 &quot; closes #400 &quot; 这样的短语来关闭拉取请求，GitHub 将关闭该拉取请求，但 Trac 插件将不会关闭 Trac 中相同编号的工单。</p>\n</aside>\n<ul>\n<li><p>如果你只想要在提交信息中引用 Django <a class=\"reference external\" href=\"https://code.djangoproject.com/\">ticket tracker</a> 中的某个 ticket ，但并*不*想要关闭它时，可以使用 “Ref #xxxxx&quot;，其中 &quot;xxxxx&quot; 是你的提交想引用的 ticket 的编号。这会触发系统自动的在被引用的 ticket 下发送一条评论。</p></li>\n<li><p>使用此模式为后端端口编写提交消息：</p>\n<div class=\"code-block\" data-language=\"none\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">None</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"None code\"><code>[&lt;Django version&gt;] Fixed &lt;ticket&gt; -- &lt;description&gt;\n\nBackport of &lt;revision&gt; from &lt;branch&gt;.\n</code></pre></div>\n<p>例如：</p>\n<div class=\"code-block\" data-language=\"none\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">None</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"None code\"><code>[1.3.x] Fixed #17028 -- Changed diveintopython.org -&gt; diveintopython.net.\n\nBackport of 80c0cbf1c97047daed2c5b41b296bbc56fe1d7e3 from main.\n</code></pre></div>\n<p>有一个 <a class=\"reference external\" href=\"https://code.djangoproject.com/wiki/MergerTips#AutomatingBackports\">维基上的脚本</a> 可以自动化这个过程。</p>\n<p>如果提交修复了回归，请将其包含在提交消息中：</p>\n<div class=\"code-block\" data-language=\"none\"><div class=\"code-block-toolbar\"><span class=\"code-block-language\">None</span><button type=\"button\" class=\"copy-button\" data-copy hidden><span class=\"copy-button-label\">Copy</span></button></div><pre role=\"group\" tabindex=\"0\" aria-label=\"None code\"><code>Regression in 6ecccad711b52f9273b1acb07a57d3f806e93928.\n</code></pre></div>\n<p>（使用引入回归的提交哈希）。</p>\n</li>\n</ul>\n</section>\n<section id=\"reverting-commits\">\n<h2>恢复提交<a class=\"heading-anchor\" href=\"#reverting-commits\"><span class=\"visually-hidden\">Link to this heading</span><span aria-hidden=\"true\">#</span></a></h2>\n<p>没有人是完美的；一些错误可能会被提交</p>\n<p>但要尽力确保不出现错误。仅仅因为我们有一个回退政策并不意味着你的责任就可以放松，你仍然需要追求最高的质量。真的：在首次提交之前，仔细检查你的工作，或者让另一个合并者在你提交之前检查它！</p>\n<p>当你发现了一个错误的提交，请遵循如下步骤：</p>\n<ul class=\"simple\">\n<li><p>可能的话，让原始作者撤回他们的提交。</p></li>\n<li><p>不要在未获得原始作者同意的情况下还原其他作者的更改。</p></li>\n<li><p>使用 git revert -- 会回退提交，但原提交依然会留在提交历史中。</p></li>\n<li><p>If the original author can't be reached (within a reasonable amount\nof time -- a day or so) and the problem is severe -- crashing bug,\nmajor test failures, etc. -- then ask for objections on the <a class=\"reference external\" href=\"https://forum.djangoproject.com/\">Django Forum</a>\nthen revert if there are none.</p></li>\n<li><p>如果问题不大（比如说冻结后的提交），就等着吧。</p></li>\n<li><p>If there's a disagreement between the merger and the reverter-to-be then try\nto work it out on the <a class=\"reference external\" href=\"https://forum.djangoproject.com/\">Django Forum</a> . If an agreement can't be reached then\nit should be put to a vote.</p></li>\n<li><p>如果该提交引入了一个已确认或已披露的安全漏洞，那么该提交可能会在未经任何允许的情况下被立即还原。</p></li>\n<li><p>如果提交的内容破坏了发布分支，发布分支的维护者可以在不经许可的情况下将该提交回退。</p></li>\n<li><p>如果错误地将主题分支推送到 &quot;django/django&quot;，请将其删除。例如，如果你做了：<code class=\"docutils literal notranslate\"><span class=\"pre\">git</span> <span class=\"pre\">push</span> <span class=\"pre\">upstream</span> <span class=\"pre\">feature_antigravity`</span></code>，那么做一个反向推送：<code class=\"docutils literal notranslate\"><span class=\"pre\">git</span> <span class=\"pre\">push</span> <span class=\"pre\">upstream:feature_antigravity</span></code>。</p></li>\n</ul>\n</section>","rootId":"committing-code","toc":[{"title":"处理 pull 请求","anchor":"handling-pull-requests","children":[]},{"title":"提交指南","anchor":"committing-guidelines","children":[]},{"title":"恢复提交","anchor":"reverting-commits","children":[]}],"breadcrumbs":[{"docname":"internals/index","title":"Django内部","url":"/zh-hans/6.0/internals/"},{"docname":"internals/contributing/index","title":"为 Django 做贡献","url":"/zh-hans/6.0/internals/contributing/"},{"docname":"internals/contributing/writing-code/index","title":"贡献代码","url":"/zh-hans/6.0/internals/contributing/writing-code/"}],"prev":{"docname":"internals/contributing/accessibility","title":"可访问性","url":"/zh-hans/6.0/internals/contributing/accessibility/"},"next":{"docname":"internals/contributing/writing-documentation","title":"编写文档","url":"/zh-hans/6.0/internals/contributing/writing-documentation/"},"formats":{"html":"/zh-hans/6.0/internals/contributing/committing-code/","markdown":"/zh-hans/6.0/internals/contributing/committing-code.md","json":"/zh-hans/6.0/internals/contributing/committing-code.json"},"source":"https://github.com/django/django/blob/stable/6.0.x/docs/internals/contributing/committing-code.txt","official":"https://docs.djangoproject.com/zh-hans/6.0/internals/contributing/committing-code/","inVersions":["6.1","6.0","5.2","5.1","5.0","4.2","4.1","4.0","3.2","3.1","3.0","2.2","2.1","2.0"],"inLocales":["en","sv","zh-hans","ga","fr","ja","id","it","pt-br","ko","es","el","pl"]}