V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lingdu666
V2EX  ›  程序员

最近在看 git 就在思考一个事情,为什么需要暂存区?

  •  
  •   lingdu666 · 2022-01-17 10:25:58 +08:00 · 8427 次点击
    这是一个创建于 1070 天前的主题,其中的信息可能已经有所发展或是发生改变。

    学分布式的时候我就知道,如果 a 直接到 b ,那么中间加一层 c ,a 到 c ,c 到 b 这样就很灵活,我猜 git 中间加一层应该是有原因的

    43 条回复    2022-01-18 12:58:57 +08:00
    xuzhzzz
        1
    xuzhzzz  
       2022-01-17 10:37:05 +08:00
    一看就是 git add . 用多了 (我也是)
    wangxn
        2
    wangxn  
       2022-01-17 10:40:10 +08:00 via Android
    git add -p 就需要这个状态。冲突状态应该也算是它的一个变种吧。
    我的理解它就是一个可以让用户整理和准备一个 commit 的中间状态,已经想不起 SVN 这些没有这个状态的工作流程是啥了。
    irobbin
        3
    irobbin  
       2022-01-17 10:41:33 +08:00
    想把 git 用的精细就需要暂存区
    mrgeneral
        4
    mrgeneral  
       2022-01-17 10:43:02 +08:00   ❤️ 1
    避免无效 commit:本次改动还没写完,但是要临时切换分支去 fix bug 、处理问题等等,需要把本次工作内容暂时缓存下来。

    当然你也可以直接先 commit 到分支,但是会导致 commit 记录就很乱,或者得再花其他精力去 rebase 之类的操作治理分支(不过随意 commit 的人也不会有这个意愿 /狗头)。
    Xbluer
        5
    Xbluer  
       2022-01-17 10:46:53 +08:00
    参考数据库设计,为了保证数据的一致性,需要一次修改多张表的字段,所以引入了事务这个概念。

    同样的,修改代码很多时候也需要修改多个文件的。比如修改了一个方法名,那么其他文件中调用了这个方法的地方都需要同步修改掉。
    gengchun
        6
    gengchun  
       2022-01-17 11:02:08 +08:00
    这个要和早期的 patch 这种工作流和内核那种大型项目联系起来。有的时候需要把一堆的 patch 文件切分成多个 commit ,必须要用 staging area 。

    切分支什么的,反正可以后面 push 前再 rebase 。而且大部分切分支的情况还是本地的分支,所以并不是一定要用到暂存。

    现代一点的工作流,或者不是很复杂的代码库,唯一常用的情况估计只有解决分支合并时的冲突这种。其它情况都不是必须。
    GuuJiang
        7
    GuuJiang  
       2022-01-17 11:09:10 +08:00 via iPhone   ❤️ 2
    假设没有暂存区,就相当于 commit(file1, file2, file3, …);
    而有了暂存区,就相当于
    stage.add(file1);
    stage.add(file2);
    stage.add(file3);
    commit(stage);

    说白了就是提供一种对命令行下交互友好的“选择待提交文件的操作”
    2i2Re2PLMaDnghL
        8
    2i2Re2PLMaDnghL  
       2022-01-17 11:17:27 +08:00   ❤️ 1
    @mrgeneral 我感觉 OP 说的是 stage ,你说的这是 stash
    misaka19000
        9
    misaka19000  
       2022-01-17 11:22:43 +08:00   ❤️ 1
    暂存区?是指 git add 之后的内容?中文怎么感觉这么别扭。。

    这个很简单,因为 command 没有选中的功能,假设修改了两个文件 A 和 B ,不借助 add 命令不能做到只提交一个文件
    gps949
        10
    gps949  
       2022-01-17 11:25:28 +08:00
    封控区、管控区、防控区
    fly2mars
        11
    fly2mars  
       2022-01-17 11:37:10 +08:00
    暂存是真方便 甚至还单独设置了快捷键 经常开发中途要改 bug 那就先把手上的暂存了 去改 bug 改完又 pop 出来
    fengci
        12
    fengci  
       2022-01-17 11:49:47 +08:00
    暂存挺好的, 本来开发需求中,临时来了紧急需求,用暂存先保留之前的代码。切回原来代码开发提交后 。再找回暂存数据继续开发
    godmiracle
        13
    godmiracle  
       2022-01-17 12:04:50 +08:00
    防止突发需求啊。。你手头上的活一个功能没完,你总不能直接 git add 吧
    uni
        14
    uni  
       2022-01-17 13:06:43 +08:00
    你说的是 stage 还是 stash

    stash 很有用的,就是手上的事情做一半要去做其他事情,那就把手上的事情 stash ,其他事情做完了在 pop 原来的事情回来继续

    至于 stage ,想起来当时刚接触 git 的时候也有疑问,后来用多了就逐渐忘记了……现在要我说的话,我觉得 stage 的作用就是给一个地方让你把你要提交的东西收集起来一起提交,不过实践中很多时间就直接 git commit -am 直接提交了……
    lingdu666
        15
    lingdu666  
    OP
       2022-01-17 13:08:22 +08:00
    @uni stage
    clrss
        16
    clrss  
       2022-01-17 13:11:33 +08:00
    应该就是上面说的方便命令行操作.

    GUI 如 JetBrains IDE, cmd-K 然后打勾就行. 流程里确实没有 stage 的概念.
    yuedashi
        17
    yuedashi  
       2022-01-17 13:17:16 +08:00 via Android
    用过 git add -p 就知道为啥了。还有谁说命令行必须 git add 才能提交?可以直接 git commit file file2
    einq7
        18
    einq7  
       2022-01-17 13:58:17 +08:00
    到底是指 git add 的,还是 stash 的
    gromit1337
        19
    gromit1337  
       2022-01-17 14:06:05 +08:00   ❤️ 1
    楼主说的是 stage 贴里一半的人在说 stash
    baiyi
        20
    baiyi  
       2022-01-17 14:39:31 +08:00   ❤️ 2
    推荐看看 《 Pro Git 》,里面有很好的解释。
    Git 的每次 commit 其实是要求原子性的,就是说它应该是一个尽可能小量的不可切分的整体。但实际使用过程中,总会不可避免的修改到不需要在这个 commit 中存在的内容,此时就需要使用 git add 把需要的内容放在暂存区,git 内部称为“索引( index )”,这个索引指明了这次提交需改的内容,它能帮助我们挑选出本次 commit 要修改的内容,区分粒度也不是文件级的。
    dddd1919
        21
    dddd1919  
       2022-01-17 14:54:01 +08:00
    相当于商城里的购物车
    Haixiang
        22
    Haixiang  
       2022-01-17 15:13:01 +08:00
    具个例子:假如你此时在开发 Button 组件,但是开发着开发着发现 Navigation 组件有个特别小特别小的 Bug ,比如说写了个双等号,要改成三等号。
    如果有没有中间的 Stage ,你就必须写完 Button 再改 Navigation ,或者先改 Navigation 再开发 Button 。
    如果有中间态,那你可以两个都同时改了,提交的时候选 Button 的文件提交,再选 Navigation 的改动提交,变变成两次很清晰的提交,而不是像 git commit -a 无脑提交,别人 Review 代码的时候就会纳闷:你开发个 Button ,搞 Navigation 干嘛。
    总的来说,git stage 可以让 git 操作更加精细,也就你说的灵活。当然这也只是 stage 的一个好处,还有在做 git diff 时也是很有帮助的。
    leafre
        23
    leafre  
       2022-01-17 15:49:45 +08:00
    预期的下一次提交
    gadfly3173
        24
    gadfly3173  
       2022-01-17 17:44:28 +08:00
    @clrss #16 打勾其实就是 stage 了
    chenliangngng
        25
    chenliangngng  
       2022-01-17 20:20:48 +08:00
    一个经常用的例子:
    新建了一个文件
    git add .
    git stash

    这样可以把新文件放到 stash 里面,如果没有暂存区,那是放不进的
    maplerecall
        26
    maplerecall  
       2022-01-17 21:07:38 +08:00 via Android
    简单的说,实践过程中很多时候不是所有的改动都需要 commit 的,例如偶尔本地写死一个值或者修改一个配置用于调试。所以 commit 的时候难免需要选择部分而不是全部改动,这些选出的就被放在 stage 这个暂存区里了。
    18000rpm
        27
    18000rpm  
       2022-01-17 23:49:20 +08:00
    https://softwareengineering.stackexchange.com/questions/119782/what-does-stage-mean-in-git#comment318087_119790
    https://stackoverflow.com/questions/4878358/why-would-i-want-stage-before-committing-in-git#comment71149979_4878399
    看过一些相关讨论,讨论重点无非是需要保证每个 commit 的完整和纯粹。但是这个需求其实根本不用中间加个 stage 区也能在提交时保证。

    有一个有用的场景是:git 的这套流程能实现只 commit 半个文件。例如在 git add 一些文件后,又对这些文件做了修改,而这些改动可能不属于本次 commit 的范围,这时 git 靠这个 stage 区就能实现半个文件的提交。从而保证了 commit 的纯粹。
    但问题是这样的场景很常见吗?
    更有一个新问题:在这套操作下,stage 区已经有文件与工作区不一致了,而 stage 区的文件是在测试代码和语法检测器测试范围之外的。在这种情况下 commit 的操作值得提倡吗?
    kidonng
        28
    kidonng  
       2022-01-18 00:24:35 +08:00
    Staging is commit action without commit identity

    把 stage 当作轻量、无负担的 commit 就行
    AItsuki
        29
    AItsuki  
       2022-01-18 01:07:27 +08:00
    以前还真没想过这种问题,大多数使用场景中确实是可以忽略暂存区的,特别是用 idea 开发的人估计都勾选了自动暂存这个功能。
    不过暂存区确实也有好用的地方,比如我写好一段代码,可以先添加到暂存区,然后又对这段代码进行尝试性优化。优化有效果就重新添加到暂存区,否则我可以直接舍弃掉当前工作区的代码然后直接提交。
    又或者你写了一大堆垃圾代码,你只想保留其中一两个文件,你可以先将它们添加到暂存区,然后直接 git clean……
    还有一个很少用的功能就是,你对一个文件修改了多行代码,但你可以只添加其中一行到暂存区。
    说白了就是暂存区能更灵活的控制提交的东西吧,你说这功能不是必要的话确实可能是不必要的,但我需要这功能,并且觉得很好用 XD
    dangyuluo
        30
    dangyuluo  
       2022-01-18 03:15:56 +08:00
    这就是设计哲学了,不懂
    Rocketer
        31
    Rocketer  
       2022-01-18 03:23:43 +08:00 via iPhone
    滥用 commit 的路过。

    我从来都是原子提交,改完一个不可分割的小部分就提交一次,哪怕只改了一个备注,以便记录自己干了点啥。

    如果需要临时切到别的分支,比如突然来了一个 bug 需要加急,那我也会提交一次,记录一下自己正在干什么,还有哪些准备做还没做的。因为我也不知道啥时候能回到这个分支,万一时间比较长,只是暂存的话就忘了该干啥了。

    所以我不需要暂存区。
    xiadong1994
        32
    xiadong1994  
       2022-01-18 04:44:59 +08:00 via iPhone
    @Rocketer 如果是 fork+pr+squash merge 的话,开发分支的 commit 记录其实无所谓
    msg7086
        33
    msg7086  
       2022-01-18 06:22:06 +08:00
    @Rocketer 你是把 commit 当成 stage 了,所以其实你还是用了一个不是 stage 的 stage 。
    msg7086
        34
    msg7086  
       2022-01-18 06:24:17 +08:00
    我算是比较常用 Stage 的。经常会遇到一个文件里只需要提交其中几行代码的情况。用 Stage 就可以把其中的几行 Stage 起来然后提交,然后再把剩下的东西再做一次提交。
    像楼上那样原子提交也是类似的效果,但是回头整理这些原子提交的时候一样要花时间。用 Stage 算是两者折中。
    yuezk
        35
    yuezk  
       2022-01-18 09:08:46 +08:00
    @misaka19000 #9
    > 这个很简单,因为 command 没有选中的功能,假设修改了两个文件 A 和 B ,不借助 add 命令不能做到只提交一个文件

    这个不太准确,git commit 后面加要提交的文件是可以做到只提交某个或者某些文件的
    sagaxu
        36
    sagaxu  
       2022-01-18 09:13:29 +08:00 via Android
    你买买买不还得有个购物车?
    sutra
        38
    sutra  
       2022-01-18 11:12:21 +08:00
    stage 是为了 commit 更加原子性,不要在一个 commit 里包含多个功能。
    ink19
        39
    ink19  
       2022-01-18 11:19:30 +08:00
    @yuezk 那这样太麻烦了。。。万一文件非常多,而且没什么规则呢
    rqtq
        40
    rqtq  
       2022-01-18 11:33:08 +08:00
    手上有很多任务时候,切来切去的时候很有用的
    yuezk
        41
    yuezk  
       2022-01-18 11:33:23 +08:00
    @ink19 #39 只是想说明一下 git commit 是支持指定提交的文件的,而不用先运行 git add 。日常中比较常用的有 git commit . 和 git commit + 单个文件,还有 git commit + 通配符。
    iugo
        42
    iugo  
       2022-01-18 12:31:42 +08:00
    我常用的一种情况:

    在做主要工作.

    顺手改了部分代码, 没完成, 暂时不想提交.

    我希望顺手的这部分保留, 但现在不要影响主要工作.
    hutusi
        43
    hutusi  
       2022-01-18 12:58:57 +08:00
    之前写另一篇关于 Git 的文章,希望对你有帮助: https://hutusi.com/articles/the-greatest-git-commit
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1102 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 18:03 · PVG 02:03 · LAX 10:03 · JFK 13:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.