bash Git中的暂存区有什么用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/49228209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What's the use of the staging area in Git?
提问by itsolidude
What is the point of git add .
or git add <filename>
to add it to the staging area? Why not just git commit -m "blabla"
?
什么是点git add .
或git add <filename>
将其添加到临时区域?为什么不只是 git commit -m "blabla"
?
I don't understand the value of the staging area.
我不明白集结区的价值。
回答by sonulohani
There are many uses of staging in git. Some are listed below:-
在 git 中有很多 staging 的用途。下面列出了一些:-
staging helps you split up one large change into multiple commits- Let's say you worked on a large-ish change, involving a lot of files and quite a few different subtasks. You didn't actually commit any of these -- you were "in the zone", as they say, and you didn't want to think about splitting up the commits the right way just then. (And you're smart enough not to make the whole thing on honking big commit!). Now the change is all tested and working, you need to commit all this properly, in several clean commits each focused on one aspect of the code changes. With the index, just stage each set of changes and commit until no more changes are pending. Really works well with git gui if you're into that too, or you can use git add -p or, with newer gits, git add -e.
staging helps in reviewing changes- Staging helps you "check off" individual changes as you review a complex commit, and to concentrate on the stuff that has not yet passed your review. Let me explain. Before you commit, you'll probably review the whole change by using git diff. If you stage each change as you review it, you'll find that you can concentrate better on the changes that are not yet staged. git gui is great here. It's two left panes show unstaged and staged changes respectively, and you can move files between those two panes (stage/unstage) just by clicking on the icon to the left of the filename. Even better, you can even stage partial changes to a file. In the right pane of git gui, right click on a change that you approve of and choose "stage hunk". Just that change (not the entire file) is now staged; in fact, if there are other, unstaged, changes in that same file, you'll find that the file now appears on both top and bottom left panes!
staging helps when a merge has conflicts- When a merge happens, changes that merge cleanly are updated both in the staging area as well as in your work tree. Only changes that did not merge cleanly (i.e., caused a conflict) will show up when you do a git diff, or in the top left pane of git gui. Again, this lets you concentrate on the stuff that needs your attention -- the merge conflicts.
staging helps you keep extra local files hanging around- Usually, files that should not be committed go into .gitignore or the local variant, .git/info/exclude. However, sometimes you want a local change to a file that cannot be excluded (which is not good practice but can happen sometimes). For example, perhaps you upgraded your build environment and it now requires an extra flag or option for compatibility, but if you commit the change to the Makefile, the other developers will have a problem. Of course you have to discuss with your team and work out a more permanent solution, but right now, you need that change in your working tree to do any work at all! Another situation could be that you want a new local file that is temporary, and you don't want to bother with the ignore mechanism. This may be some test data, a log file or trace file, or a temporary shell script to automate some test... whatever. In git, all you have to do is never to stage that file or that change. That's it.
staging helps you sneak in small changes- Let's say you're in the middle of a somewhat large-ish change and you are told about a very important bug that needs to be fixed asap. The usual recommendation is to do this on a separate branch, but let's say this fix is really just a line or two, and can be tested just as easily without affecting your current work. With git, you can quickly make and commit only that change, without committing all the other stuff you're still working on. Again, if you use git gui, whatever's on the bottom left pane gets committed, so just make sure only that change gets there and commit, then push!
暂存帮助您将一个大的更改拆分为多个提交- 假设您处理了一个大的更改,涉及大量文件和相当多的不同子任务。您实际上并没有提交任何这些 - 正如他们所说,您“在区域内”,并且您不想考虑以正确的方式拆分提交。(而且你足够聪明,不会把整个事情都放在鸣喇叭大承诺上!)。现在所有更改都经过测试并且可以正常工作,您需要正确提交所有这些,在几个干净的提交中,每个提交都专注于代码更改的一个方面。使用索引,只需暂存每组更改并提交,直到没有更多的更改挂起。如果你也喜欢 git gui,那么它真的很好用,或者你可以使用 git add -p 或者,对于较新的 gits,git add -e。
分期有助于变更- 暂存帮助您在复杂提交时“检查”个别更改,并专注于尚未通过的内容。让我解释。在提交之前,您可能会使用 git diff 查看整个更改。如果您在查看每个更改时分阶段进行,您会发现可以更好地专注于尚未分阶段的更改。git gui 在这里很棒。它的两个左侧窗格分别显示未暂存和暂存更改,您只需单击文件名左侧的图标即可在这两个窗格之间移动文件(暂存/取消暂存)。更好的是,您甚至可以对文件进行部分更改。在 git gui 的右侧窗格中,右键单击您批准的更改并选择“stage hunk”。只是那个更改(不是整个文件)现在已上演;其实如果还有其他
当合并发生冲突时,暂存会有所帮助- 当合并发生时,干净合并的更改会在暂存区和工作树中更新。当您执行 git diff 或 git gui 的左上角窗格时,只会显示未完全合并的更改(即导致冲突)。同样,这让您可以专注于需要注意的事情——合并冲突。
暂存帮助您保留额外的本地文件- 通常,不应提交的文件进入 .gitignore 或本地变体 .git/info/exclude。但是,有时您希望对无法排除的文件进行本地更改(这不是好的做法,但有时可能会发生)。例如,也许你升级了你的构建环境,它现在需要一个额外的标志或兼容性选项,但是如果你将更改提交到 Makefile,其他开发人员就会遇到问题。当然,您必须与您的团队讨论并制定更持久的解决方案,但现在,您需要在工作树中进行更改才能完成任何工作!另一种情况可能是您想要一个临时的新本地文件,并且您不想打扰忽略机制。这可能是一些测试数据、日志文件或跟踪文件,或用于自动执行某些测试的临时 shell 脚本... 任何。在 git 中,您所要做的就是永远不要暂存该文件或该更改。就是这样。
分期可以帮助你潜入一些小的变化- 假设你正处于一个有点大的变化的中间,你被告知一个非常重要的错误,需要尽快修复。通常的建议是在单独的分支上执行此操作,但假设此修复实际上只是一两行,并且可以轻松测试而不会影响您当前的工作。使用 git,您可以快速做出并仅提交该更改,而无需提交您仍在处理的所有其他内容。同样,如果您使用 git gui,那么左下方窗格中的任何内容都会被提交,所以只需确保只有该更改到达那里并提交,然后推送!
回答by torek
It's worth comparing how Git handles this—Git makes you know about and use the staging-area—to how Mercurial handles this. In Mercurial, you work exactly as you suggest: you just run hg commit
and Mercurial figures out what you changed and commits it. You do have to hg add
a newfile, but if you are just changing existing files, there is nothing special to do: you change them, and commit, and you are done.
值得将 Git 处理此问题的方式(Git 让您了解并使用暂存区)与 Mercurial 处理此问题的方式进行比较。在 Mercurial 中,您完全按照您的建议工作:您只需运行hg commit
,Mercurial 就会找出您更改的内容并提交。您确实需要hg add
一个新文件,但是如果您只是更改现有文件,则没有什么特别的事情要做:您更改它们并提交,然后就完成了。
Mercurial's behavior seems (and in my observation, has been) much more new-user-friendly. Git actually lets you get most of the same effect by using git commit -a
. That is, you just add -a
to whatever other options you will use, and Git will do pretty much the same thing as Mercurial. But this is kind of a crutch, because eventually, you will find something that Git has done that is quite inexplicable unless you know about the staging area.
Mercurial 的行为似乎(在我看来,已经)更加新用户友好。Git 实际上可以让你通过使用git commit -a
. 也就是说,您只需添加-a
您将使用的任何其他选项,Git 将做与 Mercurial 几乎相同的事情。但这有点像拐杖,因为最终,除非您了解暂存区,否则您会发现 Git 所做的某些事情是非常令人费解的。
Hidd3N's answershows a number of ways you can use Git's staging area. But if you step back a bit, and compare Mercurial and Git, you can, I think, see a lot more of what is really going on.
Hidd3N 的回答展示了多种使用 Git 暂存区的方法。但是如果你退后一点,比较 Mercurial 和 Git,我认为你可以看到更多真正发生的事情。
Remember that the job of any version control system (VCS) is to let you retrieve everycommitted version ever. (And, since both Git and Mercurial work on the snapshot of whole systembasis, they are easy to compare here. There are some much older VCSes that operate on one file at a time: you must specifically check-in / commit each individual file. Git and Mercurial make a snapshot of everything-all-at-once.) These committed snapshots should last forever, and never change at all. That is, they are read-only.
请记住,任何版本控制系统(VCS)的工作就是让您检索每一个提交的版本不断。(而且,由于 Git 和 Mercurial 都在整个系统的快照基础上工作,因此在这里很容易比较它们。有一些更旧的 VCS 一次对一个文件进行操作:您必须专门签入/提交每个单独的文件.Git 和 Mercurial 一次性制作所有内容的快照。)这些提交的快照应该永远存在,永远不会改变。也就是说,它们是只读的。
Files that are read-only are no good for working on, though. So any VCS musthave, somehow / somewhere, two separate things:
但是,只读文件不适合处理。因此,任何 VCS 都必须以某种方式/某处具有两个独立的东西:
- the place where you work on files: this is your work-tree; and
- the place that snapshots are stored: this is your version database, or repository, or some other word—Git calls these things objectswhile Mercurial has a more complicated set of structures, so let's just call them objectshere.
- 你处理文件的地方:这是你的工作树;和
- 存储快照的地方:这是你的版本数据库,或存储库,或者其他一些词——Git 将这些东西称为对象,而 Mercurial 有一组更复杂的结构,所以我们在这里只称它们为对象。
Git's object storage area has a bunch of read-only objects: in fact, one for every file, and every commit, and so on. You can add newobjects any time, but you cannot change any existing objects.
Git 的对象存储区有一堆只读对象:实际上,每个文件一个,每次提交,等等。您可以随时添加新对象,但不能更改任何现有对象。
As Mercurial demonstrates, there is no requirementfor a separate staging area: the VCS can use the work-treeas the proposed commit. When you run hg commit
, Mercurial packages up the work-tree and makes a commit from it. When you make changes in the work-tree, you change the proposed next commit. The hg status
command shows you what you're proposing to commit, which is: whatever is different between the current commit and the work-tree.
由于水银表明,没有要求单独的分期区:VCS可使用工作树作为建议提交。当您运行 时hg commit
,Mercurial 会打包工作树并从中进行提交。当您在工作树中进行更改时,您会更改建议的下一次提交。该hg status
命令向您显示您提议提交的内容,即:当前提交和工作树之间的任何不同。
Git, however, chooses to interpose this intermediate area, halfway between the read-only commits and the read/write work-tree. This intermediate area, the staging areaor indexor cache, contains the proposed next commit.
然而,Git 选择在只读提交和读/写工作树之间插入这个中间区域。这个中间区域,临时区域或索引或缓存,包含建议的下一次提交。
You start out by checking out some commit. At this point, you have threecopies of every file:
你首先检查一些提交。此时,您拥有每个文件的三个副本:
- One is in the current commit (which Git can always find by the name
HEAD
). This one is read-only; you can't change it. It's in a special, compressed (sometimes verycompressed), Git-only form. - One is in the index / staging-area. This one matches the
HEAD
one now, but it canbe changed. It's the one proposed to go into the nextcommit. This, too, is in the special Git-only form. - The last one is in your work-tree, in ordinary form where you can work on it.
- 一个在当前提交中(Git 总能通过名称找到它
HEAD
)。这是只读的;你不能改变它。它是一种特殊的、压缩的(有时非常压缩)、仅限 Git 的形式。 - 一个是在索引/暂存区。这个与
HEAD
现在匹配,但可以更改。这是建议进入下一次提交的人。这也是特殊的 Git-only 形式。 - 最后一个在您的工作树中,以普通形式,您可以在其中进行处理。
What git add
does is to copy files from your work-tree, into the staging area, overwritingthe one that used to match the HEAD
commit.
什么git add
做的是从你的工作树复制文件,到临时区域,覆盖的是用来匹配的一个HEAD
承诺。
When you run git status
, it must make two separate comparisons.One compares the HEAD
commit to the index / staging-area, to see what's going to be different in the next commit. This is what's to be committed
. The second comparison finds what's different between the index / staging-area, and the work-tree. This is what's not staged for commit
.
运行时git status
,它必须进行两个单独的比较。将HEAD
提交与索引/暂存区进行比较,看看下一次提交会有什么不同。这就是to be committed
. 第二个比较找出索引/暂存区和工作树之间的不同之处。这就是not staged for commit
.
When you run git commit -a
, Git simply does the copy-to-staging-area based on the second comparison. More precisely, it runs the equivalent of git add -u
. (It secretly does this with a temporarystaging-area, in case the commit fails for some reason, so that your regular staging-area / index is undisturbed for the duration of the commit. Some of this depends on additional git commit
arguments as well. Normally this tends to be invisible, at least until you start writing complex commit hooks.)
当您运行 时git commit -a
,Git 只是根据第二次比较执行复制到暂存区。更准确地说,它运行相当于git add -u
. (它使用临时暂存区秘密执行此操作,以防提交因某种原因失败,以便您的常规暂存区/索引在提交期间不受干扰。其中一些还取决于其他git commit
参数。通常这往往是不可见的,至少在您开始编写复杂的提交挂钩之前。)
回答by Anna Skoulikari
The staging areais like a rough draft space, it's where you can git add
the version of a file or multiple files that you want to save in your next commit(in other words in the next version of your project).
该中转区就像是一个粗略的空间草案,这是在那里你可以git add
或版本的文件,要在你的下一个保存多个文件提交(在项目的下一个版本换句话说)。
Note that you can copy versions of files into the staging area and also take them out of the staging areabefore you make your commit which is why I referred to it as a rough draft space.
请注意,您可以将文件的版本复制到暂存区,也可以在提交之前将它们从暂存区中取出,这就是我将其称为草稿空间的原因。
What the git add
command actually does is copy that version of your file from your working directory to the staging area.
该git add
命令的实际作用是将该版本的文件从您的工作目录复制到暂存区。
(This is a common misconception, people may think in their mental model that the file is moved but actually it is copied.)
(这是一个常见的误解,人们可能会在他们的心理模型中认为文件被移动了,但实际上它被复制了。)
The journey a file takes to have an updated version of it added to your repository:
将文件的更新版本添加到您的存储库所需的过程:
- 1??It is edited in your working directory. The working directory is like a work bench it is where you edit your files, add new files and delete files.
- 2??Then the file is added to the staging area using the
git add
command - 3??Finally it is included in the next commit when you use the
git commit
command
- 1??它在您的工作目录中编辑。工作目录就像一个工作台,您可以在其中编辑文件、添加新文件和删除文件。
- 2??然后使用
git add
命令将文件添加到暂存区 - 3??最后在使用
git commit
命令的时候包含在下一次提交中
The nice thing about being able to choose which files to add to the staging area and to include in a commit is that you can organizeyour work better this way.
能够选择将哪些文件添加到暂存区并包含在提交中的好处是,您可以通过这种方式更好地组织您的工作。
You can add all the updated files that are related to one piece of workand when you make a commit you can add a message that mentions that piece of work.
您可以添加与一项工作相关的所有更新文件,并且在进行提交时,您可以添加一条提及该工作的消息。
This way you can organize your commits better.
这样你就可以更好地组织你的提交。
This videoexplains all the above in a really simple and visual manner so it may be helpful!
该视频以非常简单和直观的方式解释了上述所有内容,因此可能会有所帮助!
p.s. Another little tidbit, in case anyone is curious where the staging area really is in your .git directory. It is represented by the index filein your .git directory!
ps 另一个小花絮,以防有人好奇暂存区在您的 .git 目录中的真正位置。它由.git 目录中的索引文件表示!
回答by Ekansh Gautam
If you think staging is a useless then you may be aware of full power of git and software development too.Staging means that you want to commit those files to your current branch. Sometimes it happens that you may not want to commit some files so those files will not be staged for commit.
如果您认为暂存没有用,那么您可能也意识到 git 和软件开发的全部功能。暂存意味着您希望将这些文件提交到当前分支。有时,您可能不想提交某些文件,因此这些文件不会被暂存以进行提交。
For example :- some default configuration that are specific to your system so you may not want to commit those config files to the branch where in everyone is using those. I hope it clears your doubt! :-)
例如:- 某些特定于您的系统的默认配置,因此您可能不想将这些配置文件提交到每个人都使用这些配置文件的分支。希望能解开你的疑惑!:-)