{"title":"提交代码","version":"5.2","locale":"zh-hans","docname":"internals/contributing/committing-code","url":"/zh-hans/5.2/internals/contributing/committing-code/","canonical":"https://djangodocs.dev/zh-hans/5.2/internals/contributing/committing-code/","summary":"本部分针对提交者以及任何有兴趣了解如何为 Django 贡献代码的人员。 如果您是想向 Django 贡献代码的社区成员，请查看 使用 Git 和 GitHub 工作 处理 pull 请求 Link to this heading # 因为Django现在是托管在GitHub上的，所以大多数补丁都是以 pull…","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>本部分针对提交者以及任何有兴趣了解如何为 Django 贡献代码的人员。 如果您是想向 Django 贡献代码的社区成员，请查看 <a class=\"reference internal\" href=\"/zh-hans/5.2/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>此外，在将代码提交到Django的Git存储库时，请遵循以下准则：</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>以过去时态写出详细的提交消息，而不是现在时。</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;</p></li>\n</ul>\n<p>提交消息最多应为72个字符。 应该有一个主题行，用空白行分隔，然后是72个字符行的段落。 限制很软。 对于主题行，越短越好。 在提交消息的主体中，更多细节优于更少：</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</code></pre></div>\n<p>可以在提交消息中添加对贡献者的感谢：“感谢 A 提供报告，B 提供补丁，C 提供审查。” 也推荐使用 git 的 <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> 功能。</p>\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/5.2/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/5.2/internals/"},{"docname":"internals/contributing/index","title":"为 Django 做贡献","url":"/zh-hans/5.2/internals/contributing/"},{"docname":"internals/contributing/writing-code/index","title":"贡献代码","url":"/zh-hans/5.2/internals/contributing/writing-code/"}],"prev":{"docname":"internals/contributing/accessibility","title":"Accessibility","url":"/zh-hans/5.2/internals/contributing/accessibility/"},"next":{"docname":"internals/contributing/writing-documentation","title":"编写文档","url":"/zh-hans/5.2/internals/contributing/writing-documentation/"},"formats":{"html":"/zh-hans/5.2/internals/contributing/committing-code/","markdown":"/zh-hans/5.2/internals/contributing/committing-code.md","json":"/zh-hans/5.2/internals/contributing/committing-code.json"},"source":"https://github.com/django/django/blob/stable/5.2.x/docs/internals/contributing/committing-code.txt","official":"https://docs.djangoproject.com/zh-hans/5.2/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"]}