在 Git 中仅提交文件的部分更改
当我在 Git 中更改文件时,如何才能仅提交部分更改?
例如,如何才能仅提交文件中已更改的 30 行中的 15 行?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
当我在 Git 中更改文件时,如何才能仅提交部分更改?
例如,如何才能仅提交文件中已更改的 30 行中的 15 行?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(30)
如果是在
Windows
平台上,我认为git gui
是非常好的工具,可以stage
/commit
几行代码未暂存
文件1. Hunkwise:
unstagged Changes
部分选择文件Stage Hunk for commit
2。 逐行:
unstagged Changes
部分选择文件Stage Lines for commit
3. 如果您想暂存除几行之外的完整文件:
未暂存的更改
部分选择文件Ctrl+T(暂存要提交的文件)
Staging Changes
部分UnStage Lines for commit
If it's on
Windows
platform, in my opiniongit gui
is very good tool tostage
/commit
few lines fromunstaged
file1. Hunk wise:
unstagged Changes
sectionStage Hunk for commit
2. Line wise:
unstagged Changes
sectionStage Lines for commit
3. If you want to stage the complete file except couple of lines:
unstagged Changes
sectionCtrl+T (Stage file to commit)
Staged Changes
SectionUnStage Lines for commit
来自此 2018 年答案的评论:
现在(2022 年 8 月)支持:
From the comments of this 2018 answer:
It is now (Aug. 2022) supported:
对于 emacs,还有 gitsum
For emacs there is also gitsum
正如上面的一个答案所示,您可以使用
<代码>
git add --patch 文件名.txt
或简称
<代码>
git add -p 文件名.txt
...但是对于存储库中已有的文件,在 s 中直接在提交命令上使用 --patch 标志会更好(如果您使用的是足够新的 git 版本):
<代码>
git commit --patch 文件名.txt
...或者,再一次,缩写形式
<代码>
git commit -p 文件名.txt
...然后使用提到的键(y/n 等)来选择要包含在提交中的行。
As one answer above shows, you can use
git add --patch filename.txt
or the short-form
git add -p filename.txt
... but for files already in you repository, there is, in s are much better off using --patch flag on the commit command directly (if you are using a recent enough version of git):
git commit --patch filename.txt
... or, again, the short-form
git commit -p filename.txt
... and then using the mentioned keys, (y/n etc), for choosing lines to be included in the commit.
我想添加非常具体的行号(不幸的是,
git add --patch
将这些行与其他不需要的行一起呈现)。 这是我解决的方法git add --patch
y
和n
暂存或不暂存大块,直到到达相关大块e
(编辑块)Git 将在 vim 中打开文件并为您提供此信息(第一行是重要的位)
-
行,使其成为+
行,只需删除它们即可。 使用 vim 键绑定 执行此操作。额外
要验证它是否有效,请运行 git diff --staged 来查看带有行的特定文件 /em> 上演了!
I wanted to add very specific line numbers (and unfortunately
git add --patch
presented those lines with other unwanted lines). Here's how I solvedgit add --patch <filename>
y
andn
to stage or not stage hunks until you reach the relevant hunke
(to edit the hunk)Git will open the file in vim and give you this info (the first lines are the important bits)
-
lines, make them+
lines simply delete them. Do this using vim keybindings.Bonus
To verify that it worked, run
git diff --staged
to see the specific files with lines that are staged!git-meld-index -- 引用网站:
git-meld-index运行meld -- 或任何其他 git difftool(kdiff3、diffuse 等)-- 允许您以交互方式暂存对 git 索引(也称为 git 暂存区域)的更改。
这类似于 git add -p 和 git add --interactive 的功能。 在某些情况下,meld 比 git add -p 使用起来更容易/更快。 这是因为 meld 允许您执行以下操作:
用法
在 git 存储库中,运行:
您将看到 meld (或您配置的 git difftool)弹出:
LEFT:包含从工作树复制的文件的临时目录
右:包含索引内容的临时目录。 这还包括尚未在索引中但在工作副本中已修改或未跟踪的文件 - 在这种情况下,您将看到 HEAD 中的文件内容。
编辑索引(右侧)直到满意为止。 需要的时候记得保存。
完成后,关闭 meld,git-meld-index 将更新索引以匹配您刚刚编辑的 meld 右侧临时目录的内容。
git-meld-index -- quoting from the website:
git-meld-index runs meld -- or any other git difftool (kdiff3, diffuse, etc.) -- to allow you to interactively stage changes to the git index (also known as the git staging area).
This is similar to the functionality of git add -p, and git add --interactive. In some cases meld is easier / quicker to use than git add -p. That's because meld allows you, for example, to:
Usage
In a git repository, run:
You'll see meld (or your configured git difftool) pop up with:
LEFT: temporary directory contining files copied from your working tree
RIGHT: temporary directory with the contents of the index. This also includes files that are not yet in the index but are modified or untracked in the working copy -- in this case you'll see the file contents from HEAD.
Edit the index (right hand side) until happy. Remember to save when needed.
When you're done, close meld, and git-meld-index will update the index to match the contents of the temporary directory on the right hand side of meld that you just edited.
git-cola 是一个很棒的 GUI,并且内置了此功能。 只需选择要暂存的行并按 S 即可。 如果没有做出选择,则完整的大块将上演。
git-cola is a great GUI and also has this feature built-in. Just select the lines to stage and press S. If no selection is made, the complete hunk is staged.
您可以使用 Eclipse IDE,每个修改的本地文件都可以与暂存区域进行比较,在这个并排差异视图中,您可以自由选择将哪个块从本地复制到暂存区域,或者在相反的情况下,回滚本地更改舞台区域。
但还有更多:),所有图形 git 客户端也都执行该块暂存(git add -p),但我知道没有一个可以做到这一点:直接在暂存区域中编辑,因此可以更精细地选择同一行或同一块上的多个更改(或者甚至写入/删除/更新本地从未存在的内容),例如在补丁级别工作的“git add -e”,但没有破坏补丁内容的风险。
此外,由于它在 diff 视图中使用常规文本编辑器,因此您可以使用语法颜色来帮助,并且可以执行文本替换操作(更改所有缩进类型,重命名在许多地方使用的局部变量,...)以开始单独提交一些在提交“真正的”更改之前重新格式化/重构,但不将所有文件更改嵌入到同一个提交中。
当然,Eclipse 更面向 Java,但由于其强大的 git staging 编辑器,它也可以用于其他语言。 有一个基于 Eclipse 的免费产品,只专注于 git 操作,称为 GitEye : https://www.collab.net/ downloads/giteye 但似乎没有维护得更好,最好使用基本的 Eclipse 发行版,例如: https://www.eclipse.org/downloads/packages/release/2020-12/r/eclipse-ide-java-developers
编辑:自 IntelliJ 以来2020.3 允许使用真正的 git 索引,现在可以像 Eclipse 一样直接编辑暂存区域
You can use Eclipse IDE, each modified local files can be compared vs the staged area and in this side by side diff view, you are free to choose which hunk to copy from local to staged area, or in the opposite, rollback local change from the staged area.
But there's more :), all graphical git clients do that hunk staging too (git add -p), but none I know can do that : directly edit in the staged area so several changes on same line or same hunk can be more fined picked up (or even write/delete/update stuff that never exists locally), like a "git add -e" working at patch level but without the risk to break the patch content.
Moreover since it's with the regular text editor in the diff view, you have syntax color to help and you can do text replace operations (change all indentation types, rename a local variable use in many place, ...) to start committing separately some reformat / refactor before committing your "real" change but without embedding all file changes in the same commit.
Sure Eclipse is more Java oriented but because of its powerful git staging editor, it can be used for other language too. There is an Eclipse based free product only focusing git operation called GitEye : https://www.collab.net/downloads/giteye but seems not maintained so better to use a basic Eclipse distrib like : https://www.eclipse.org/downloads/packages/release/2020-12/r/eclipse-ide-java-developers
Edit : since IntelliJ 2020.3 allows to work with real git index, it is now capable to edit directly the staged area like Eclipse
在所有这些工具中,我最喜欢 Fork (尽管不是免费的)!
与其他的相比,它使用起来非常时尚和优雅,点击鼠标旁边的按钮即可进行块或线分段。
另一个选择是 GitKraken,有趣但更复杂、更强大!
Among all these tools, I love Fork the most (though not free)!
Compared with other ones, it is very sleek and elegant to use, click the button alongside your mouse would do hunk or line staging.
Another option is GitKraken, fun but more complex and powerful!
您可以使用:
或简称:
Git 会将您的文件分解为它认为合理的“块”(文件的一部分)。 然后它会提示您这个问题:
这是每个选项的描述:
+
/-
替换为#
来手动编辑该块(感谢 veksen)如果文件尚未在存储库中,您可以先执行
git add -N< /代码>。 之后您可以继续使用 git add -p
。之后,您可以使用:
git diff --staged
来检查您是否暂存了正确的更改git reset -p
以取消暂存错误添加的块git commit -v< /code> 在编辑提交消息时查看您的提交。
请注意,这与 git format-patch 命令有很大不同,后者的目的是将提交数据解析为 .patch 文件。
未来参考:Git 工具 - 交互式暂存
You can use:
or for short:
Git will break down your file into what it thinks are sensible "hunks" (portions of the file). It will then prompt you with this question:
Here is a description of each option:
+
/-
by#
(thanks veksen)If the file is not in the repository yet, you can first do
git add -N <filename>
. Afterwards you can go on withgit add -p <filename>
.Afterwards, you can use:
git diff --staged
to check that you staged the correct changesgit reset -p
to unstage mistakenly added hunksgit commit -v
to view your commit while you edit the commit message.Note this is far different than the
git format-patch
command, whose purpose is to parse commit data into a.patch
files.Reference for future: Git Tools - Interactive Staging
您可以使用 git add --interactive 或 git add -p file> ,然后使用 git commit > (不是
git commit -a
); 请参阅 git-add 手册页中的交互模式,或者直接按照指示。现代 Git 还具有 git commit --interactive 和 git commit --patch,这是交互式提交中修补选项的快捷方式。
如果您更喜欢通过 GUI 进行操作,可以使用 git-gui。 您可以简单地标记要包含在提交中的块,方法是右键单击它们并选择:
如果您只想添加 hunk 的某些行,您还可以选择所需的行,右键单击它们,然后:
我个人发现它比使用
git add -i
更容易。 其他 git GUI,例如 QGit 或 GitX,也可能具有此功能。You can use
git add --interactive
orgit add -p <file>
, and thengit commit
(notgit commit -a
); see Interactive mode in git-add manpage, or simply follow instructions.Modern Git has also
git commit --interactive
(andgit commit --patch
, which is shortcut to patch option in interactive commit).If you prefer doing it from GUI, you can use git-gui. You can simply mark chunks which you want to have included in commit by right clicking them and selecting:
If you want to add only certain lines of the hunk, you can also select the lines you want, right click them and:
I personally find it easier than using
git add -i
. Other git GUIs, like QGit or GitX, might also have this functionality as well.git gui 在 diff 视图下提供了此功能。 只需右键单击您感兴趣的行,您应该会看到“暂存此行以提交”菜单项。
git gui provides this functionality under the diff view. Just right click the line(s) you're interested in and you should see a "stage this line to commit" menu item.
我相信 git add -e myfile 是最简单的方法(至少是我的偏好),因为它只是打开一个文本编辑器,让您选择要暂存的行和不暂存的行。
关于编辑命令:
新增内容:
删除的内容:
修改内容:
有关 git add 的所有详细信息都可以在 git --help add 上找到
I believe that
git add -e myfile
is the easiest way (my preference at least) since it simply opens a text editor and lets you choose which line you want to stage and which line you don't.Regarding editing commands:
added content:
removed content:
modified content:
Every details about
git add
are available ongit --help add
如果您碰巧使用 VS Code,那么您很幸运。 选择要暂存的范围,然后使用
Git:暂存选定范围
暂存它们,并根据需要提交。我录制了一个 gif 来演示我的意思:
If you happen to be using VS Code, you're in luck. Select the range that you want to stage, then use
Git: Stage Selected Ranges
to stage them, and commit if you want.I recorded a gif to demonstrate what I meant:
如果您使用 vim,您可能想尝试一下名为 fugitive 的优秀插件。
您可以使用
:Gdiff
查看工作副本和索引之间的文件差异,然后使用经典的 vim diff 命令(如dp
)向索引添加行或块。 将修改保存在索引中并使用:Gcommit
提交,然后就完成了。非常好的介绍性截屏这里(特别参见第 2 部分)。
If you are using vim, you may want to try the excellent plugin called fugitive.
You can see the diff of a file between working copy and index with
:Gdiff
, and then add lines or hunks to the index using classic vim diff commands likedp
. Save the modifications in the index and commit with:Gcommit
, and you're done.Very good introductory screencasts here (see esp. part 2).
值得注意的是,要使用 git add --patch 来创建新文件,您需要首先使用 git add --intent-to-add 将文件添加到索引:
Worth noting that to use
git add --patch
for a new file you need to first add the file to index withgit add --intent-to-add
:我强烈建议使用 Atlassian 的 SourceTree。 (它是免费的。)它使这变得微不足道。 您可以快速轻松地暂存单个代码块或单个代码行。
I would strongly recommend using SourceTree from Atlassian. (It's free.) It makes this trivial. You can stage individual hunks of code or individual lines of code quickly and easily.
当我有很多更改,并且最终会根据更改创建一些提交时,我想在暂存之前暂时保存我的起点。
像这样:
Whymarr 的答案是我通常做的,除了有时会有很多变化,我可以告诉我在准备事情时可能会犯错误,并且我想要一个可以依靠的承诺状态来进行第二次传递。
When I have a lot of changes, and will end up creating a few commits from the changes, then I want to save my starting point temporarily before staging things.
Like this:
Whymarrh's answer is what I usually do, except sometimes there are lots of changes and I can tell I might make a mistake while staging things, and I want a committed state I can fall back on for a second pass.
添加之前的答案,如果您更喜欢使用命令行,输入 git add -e myfile 可以让您选择逐行选择要提交的内容,因为此命令将打开一个编辑器,其中包含差异,如下所示:
正如您所知,以
+
开头的行是添加,以-
开头的行是删除。 所以:-
替换为空格即可。
这就是 git add -h 所说的关于以这种方式添加文件(修补文件)的内容:
警告:请勿更改文件的内容,这不是这样做的好地方。 只需更改已删除或添加的行的运算符即可。
Adding on a previous answer, if you prefer using the command line, entering
git add -e myfile
gives you the choice to choose line by line what you want to commit because this command will open an editor with the differences, like so:As you may known lines that start with
+
are addtions, lines that start with-
are deletions. So:-
with space.
This is what
git add -h
says about adding files this way (patching files):Caution: do not change the content of the file, this is not a good place to do so. Just change the operators of deleted or added lines.
IntelliJ IDEA(我猜该系列的所有其他产品)自那时起就内置了对部分提交的支持v2018.1。
IntelliJ IDEA (and I guess all other products of the series) has built-in support for partial commits since v2018.1.
如果您使用 emacs,请查看 Magit,它为 emacs 提供了 git 界面。 它很好地支持暂存块(文件的一部分)。
Should you use emacs, take a look at Magit, which provides a git interface for emacs. It supports staging hunks (parts of files) quite well.
首先,我们可以看看有哪些变化。
如果它显示在不同的块中,我们可以
通过接受或拒绝更改(y或n)来使用。
如果没有,我们仍然可以借助 VS Code
First, we can look at what the changes are.
If it shows in different chunks, we can use
by accepting or rejecting changes ( y or n).
If not we can still do it with help of VS Code
对于使用 Git Extensions 的用户:
在“提交”窗口中,选择要部分提交的文件,然后在右侧窗格中选择要提交的文本,然后右键单击所选内容并选择从上下文菜单中“暂存选定的行”。
For those who use Git Extensions:
In the Commit window, select the file you want to partially commit, then select the text you want to commit in the right pane, then right-click on the selection and choose 'Stage selected lines' from the context menu.
这个问题问出来已经有10年了。 我希望这个答案对某人有用。 正如这里的答案中提到的,GUI不是一个选项,Andrej Shadura的git-crecord 工具 有助于带来一个交互式窗口,我们可以在其中选择要提交的行。
按如下方式设置扩展:
cd 到您的 git 存储库并按如下方式调用它:
这将显示一个可以使用的交互式界面,如下所示。 按以下键将执行某些操作:
显示示例用法的截屏
It's been 10 years since this question was asked. And I hope this answer will be useful to someone. As mentioned in the answer here, where GUI is not an option, Andrej Shadura's git-crecord tool helps bring an interactive window in which we can select the lines to commit.
Set up the extension as follows:
cd to your git repo and invoke it as follows:
This would bring up an interactive interface which can be used as shown below. Pressing the following keys will do certain actions:
Screencast showing a sample usage
与 jdsumsion 的答案非常相似,您也可以存储当前的工作,然后使用像 meld 这样的 difftool 从存储中提取选定的更改。 这样你甚至可以非常容易地手动编辑这些块,这在 git add -p 中有点痛苦:
使用 stash 方法让你有机会测试你的代码是否仍然有效,在你提交之前。
Much like jdsumsion's answer you can also stash your current work but then use a difftool like meld to pull selected changes from the stash. That way you can even edit the hunks manually very easy, which is a bit of a pain when in
git add -p
:Using the stash method gives you the opportunity to test, if your code still works, before you commit it.
vim-gitgutter 插件可以在不离开 vim 编辑器的情况下上演帅哥
除此之外,它还提供其他很酷的功能,例如一些现代 IDE 中的 diff 符号列
如果只应暂存 hunk 的一部分 vim-fugitive
允许视觉范围选择,然后
:'<,'>diffput
或:'<,'>diffget
来暂存/恢复单个行更改。vim-gitgutter plugin can stage hunks without leaving vim editor using
Beside this, it provides other cool features like a diff sign column as in some modern IDEs
If only part of hunk should be staged vim-fugitive
allows visual range selection then
:'<,'>diffput
or:'<,'>diffget
to stage/revert individual line changes.尝试了 git add -p filename.x ,但在 Mac 上,我找到了 gitx (http: //gitx.frim.nl/ 或 https://github.com/pieter/gitx)更容易准确地提交我想要的行。
Tried out
git add -p filename.x
, but on a mac, I found gitx (http://gitx.frim.nl/ or https://github.com/pieter/gitx) to be much easier to commit exactly the lines I wanted to.使用 TortoiseGit:
With TortoiseGit:
对于 Atom 用户,包 github 包括交互式暂存,采用 git gui 风格。 有关快捷方式,请参阅该包的文档。
使用 Atom 允许使用深色背景的主题(默认情况下,
git gui
有白色背景)。For Atom users, the package github includes interactive staging, in the style of
git gui
. For shortcuts see the package's documentation.Using Atom allows working with a theme that has dark background (by default,
git gui
has a white background).我想将 lazygit 添加到工具列表中。 这是一个很好的命令行 GUI(即,即使不允许 X 转发,也可以通过 ssh 工作)。 它具有广泛的功能(例如,选择要提交的行、交互式变基)、有用的着色,并且使用起来相对简单。 可以通过多种方式安装(go、conda、包管理器……)。 仍在积极开发/维护。
I want to add lazygit to the list of tools. It's a nice command-line gui (i.e., works through ssh even if X forwarding is not allowed). It has extensive functionalities (e.g., select lines to commit, interactive rebase), helpful coloring, and is relatively simple to use. Can install in a variety of ways (go, conda, package manager,...). Still actively developed/maintained.