V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lingdu666
V2EX  ›  程序员

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

  •  
  •   lingdu666 · 124 天前 · 6729 次点击
    这是一个创建于 124 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

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

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

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

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

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

    GUI 如 JetBrains IDE, cmd-K 然后打勾就行. 流程里确实没有 stage 的概念.
    yuedashi
        17
    yuedashi  
       124 天前 via Android
    用过 git add -p 就知道为啥了。还有谁说命令行必须 git add 才能提交?可以直接 git commit file file2
    einq7
        18
    einq7  
       124 天前
    到底是指 git add 的,还是 stash 的
    gromit1337
        19
    gromit1337  
       124 天前   ❤️ 1
    楼主说的是 stage 贴里一半的人在说 stash
    baiyi
        20
    baiyi  
       124 天前   ❤️ 2
    推荐看看 《 Pro Git 》,里面有很好的解释。
    Git 的每次 commit 其实是要求原子性的,就是说它应该是一个尽可能小量的不可切分的整体。但实际使用过程中,总会不可避免的修改到不需要在这个 commit 中存在的内容,此时就需要使用 git add 把需要的内容放在暂存区,git 内部称为“索引( index )”,这个索引指明了这次提交需改的内容,它能帮助我们挑选出本次 commit 要修改的内容,区分粒度也不是文件级的。
    dddd1919
        21
    dddd1919  
       123 天前
    相当于商城里的购物车
    Haixiang
        22
    Haixiang  
       123 天前
    具个例子:假如你此时在开发 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  
       123 天前
    预期的下一次提交
    gadfly3173
        24
    gadfly3173  
       123 天前
    @clrss #16 打勾其实就是 stage 了
    chenliangngng
        25
    chenliangngng  
       123 天前
    一个经常用的例子:
    新建了一个文件
    git add .
    git stash

    这样可以把新文件放到 stash 里面,如果没有暂存区,那是放不进的
    maplerecall
        26
    maplerecall  
       123 天前 via Android
    简单的说,实践过程中很多时候不是所有的改动都需要 commit 的,例如偶尔本地写死一个值或者修改一个配置用于调试。所以 commit 的时候难免需要选择部分而不是全部改动,这些选出的就被放在 stage 这个暂存区里了。
    18000rpm
        27
    18000rpm  
       123 天前
    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  
       123 天前
    Staging is commit action without commit identity

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

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

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

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

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

    在做主要工作.

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

    我希望顺手的这部分保留, 但现在不要影响主要工作.
    hutusi
        43
    hutusi  
       123 天前
    之前写另一篇关于 Git 的文章,希望对你有帮助: https://hutusi.com/articles/the-greatest-git-commit
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2583 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 06:40 · PVG 14:40 · LAX 23:40 · JFK 02:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.