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

git checkout -- file 时能否自动备份一下修改过的文件?

  •  
  •   guoqiao · 2014-02-23 05:07:57 +08:00 · 6702 次点击
    这是一个创建于 3707 天前的主题,其中的信息可能已经有所发展或是发生改变。
    昨天修改一个问题, 由于反复尝试, 一不小心改了同一个文件夹下的好几个文件, 如:

    dir/a.py
    dir/b.py
    dir/c.py
    ....

    但是有一个文件例如c.py是不想提交的.
    我执行 git checkout 时手太快, 输入git co -- dir就 enter 了.
    这时意识到杯具鸟...
    由于修改的代码还是比较多的, 当时真是惊出一身冷汗,心想2个小时的工作没了...
    还好我 vim 里的 buffer 还在, 重新逐一保存了下, 都救回来了.

    我记得以前用别的 VCS, 每次你恢复文件的时候, 会创建一个c.py.orig 之类的备份.
    在 git 下, 有类似的功能吗? 或者, 大家用 git 时是如何避免我这样的杯具的?
    第 1 条附言  ·  2014-02-23 11:32:56 +08:00
    貌似我的问题描述得很不清楚...罢了, 以后注意点就是了.
    27 条回复    2016-05-20 09:35:24 +08:00
    jabbany
        1
    jabbany  
       2014-02-23 05:10:36 +08:00
    先 stash 一下?
    alexrezit
        2
    alexrezit  
       2014-02-23 08:00:06 +08:00
    git stash
    wwqgtxx
        3
    wwqgtxx  
       2014-02-23 08:16:46 +08:00 via Android
    每次都用git-gui,提交前还能看一下diff,避免绝大多数问题
    guoqiao
        4
    guoqiao  
    OP
       2014-02-23 10:36:26 +08:00
    @alexrezit 使用 statsh 的场景是暂时中断当前的工作,回到代码库的最新版,然后事后还能回到工作版本. 跟我这里的场景有点不一样. 我并不是要回到最新版. 我是希望能自动备份下,避免出错. 也就是我 git checkout -- c.py的时候,能自动给我建一个c.py.orig
    guoqiao
        5
    guoqiao  
    OP
       2014-02-23 10:38:11 +08:00
    @wwqgtxx 用 terminal 用惯了, 不想多开一个程序. 本质上, 你用 gui,如果 checkout 时不小心勾选了全部文件, 也会有一样的问题. 只是稍微直观了一点而已.
    xcatliu
        6
    xcatliu  
       2014-02-23 10:40:58 +08:00
    任何 git add 过的文件,都会在 git 历史中保留此次 hash 值,找到即可 reset 恢复文件。
    具体怎么找到可以用 git reflog 或者 git log -g 找到历史记录。
    guoqiao
        7
    guoqiao  
    OP
       2014-02-23 10:42:02 +08:00
    @xcatliu 没提交过的修改也行??
    xcatliu
        8
    xcatliu  
       2014-02-23 10:45:05 +08:00
    @guoqiao 没提交过的也可以,只要 add 就会在 git 中留下记录。
    如果 add 都没有过就无法使用 git 恢复了。。
    guoqiao
        9
    guoqiao  
    OP
       2014-02-23 10:47:01 +08:00
    @xcatliu 这么说, 我每改动一下文件, git 都会给我备份下? 要不要这么辛苦...
    G_virus
        10
    G_virus  
       2014-02-23 10:53:31 +08:00   ❤️ 1
    只要 add 过的文件就可以用 fsck 找回,以前在 stackoverflow 上曾经回答过一个这样的问题。

    http://stackoverflow.com/questions/14475003/recover-files-after-git-rm-rf/14475432#14475432

    不过lz的情况是 add 都没有 add 过的话,那确实没办法了……因为没有任何相关的信息保存到 git 里。
    xcatliu
        11
    xcatliu  
       2014-02-23 10:56:13 +08:00
    @guoqiao 修正一下,git reflog 或者 git log -g 好像是恢复 commit 的,add 过的怎么恢复不记得了。。
    Mutoo
        12
    Mutoo  
       2014-02-23 10:57:02 +08:00
    看了一下 git 的 client-side hooks 好像也没有能满足你的要求的。只有一个 post-checkout 是在 checkout 之后。

    我想到一个很麻烦的方法就是你在本地有两个工作目录,一个用来 commit 一个用来 checkout,中间用 rsync 同步,可以用 rsync 的 --backup 实现备份
    9hills
        13
    9hills  
       2014-02-23 11:09:48 +08:00
    @guoqiao 必须是在stage区域的才能通过git fsck找回。

    话说你这种使用方法就不对:有一个文件例如c.py是不想提交的.

    如果有一个文件不想提交,请单开分支commit或者加到gitignore中忽略掉。而不是连stage区域都不放,这个丢了神仙也没办法的。
    9hills
        14
    9hills  
       2014-02-23 11:11:05 +08:00
    git的精髓是一次只做一件事,如果一次要做好几件事,比如既要改bug又要开发新feature,请善用分支功能。每个分支只做一件事
    guoqiao
        15
    guoqiao  
    OP
       2014-02-23 11:29:02 +08:00
    @9hills
    "如果有一个文件不想提交,请单开分支commit或者加到gitignore中忽略掉。而不是连stage区域都不放,这个丢了神仙也没办法的。"

    我是调试时在那个文件里加了一行 print xxx, 莫非为了这个我要开分支...
    加 ignore 也不对, 我不是要 ignore, 我只是要撤销本次的修改.
    guoqiao
        16
    guoqiao  
    OP
       2014-02-23 11:31:41 +08:00
    @9hills 我知道道理如此, 这不止是 git 的精髓, 这也是 Unix 的精髓.
    但是, 这种道理看你怎么想了.
    比如, 如果你用过 hg, 你就知道 git 的 pull 其实做了两件事, 对应到 hg 里是:
    hg pull & hg update

    显然 hg 的做法更严谨, 一次一件事. 但是你绝对会为这件事很恼火.
    guoqiao
        17
    guoqiao  
    OP
       2014-02-23 11:35:51 +08:00
    @Mutoo 还是省省吧, 为了解决一个小问题, 这会耽误你更多时间, 然后, 带来更多问题...
    guoqiao
        18
    guoqiao  
    OP
       2014-02-23 11:43:31 +08:00
    其实我一直想说, git 的命令行接口简直是反人类, 就没几个直观的.
    从回答也能看出, 大家对 git 的理解五花八门, 人人都觉得自己的workflow是对的.
    hg 比 git 要易用太多, 只可惜大势已去...
    FrankFang128
        19
    FrankFang128  
       2014-02-23 11:47:38 +08:00 via Android
    用 JetBrain 的IDE,有本地历史!
    9hills
        20
    9hills  
       2014-02-23 11:56:44 +08:00
    @guoqiao 如果是print xxx的话,被清理掉也没啥损失吧。。
    guoqiao
        21
    guoqiao  
    OP
       2014-02-23 13:28:30 +08:00
    @9hills 汗, 你真的没有仔细看我的问题, 或者我描述得太差劲了...
    我就是为了清理掉这个文件, 结果不小心把所有的修改都清理了
    本来是想执行:
    git checkout -- dir/c.py
    结果手太快, 成了:
    git checkout -- dir
    于是a.py, b.py, c.py都被恢复了.
    9hills
        22
    9hills  
       2014-02-23 13:40:21 +08:00
    @guoqiao 那你应该先add修改的a.py和b.py,然后checkout 掉c.py

    不过这个一般是误操作啦,git多add总没错,不爽可以reset HEAD么
    SoloCompany
        23
    SoloCompany  
       2014-02-24 01:47:36 +08:00 via iPad
    一直弄不懂git的命令行,为什么没有revert命令只有checkout来代替revert功能,比如svn你如果revert一个目录不加recursive参数是不让执行的,这样也不会发生类似的误操作了。还有另一点就是难道不能单独提交若干个文件的吗?反正我是试过好几次都没成功,为了提交文件必须把不想提交的文件恢复,很麻烦
    guoqiao
        24
    guoqiao  
    OP
       2014-02-24 04:56:21 +08:00
    @SoloCompany
    可以单独提交文件的,例如我这里的情况, 你可以只提交a.py:
    git commit -m "foo" dir/a.py

    不过我同意, git 确实太晦涩, 和 linux 一样, 强大, 但是太不易用.
    额, 在它俩如日中天的今天说这种话肯定会被喷...
    先闪了
    guoqiao
        25
    guoqiao  
    OP
       2014-02-24 05:00:39 +08:00
    @SoloCompany 我强烈认为 checkout 命令是设计缺陷.
    明明有 branch 命令, 却要用 checkout -c 来创建分支.
    切换分支也是checkout xxx
    恢复文件也是这货, 为了区分文件和分支名, 要写成 checkout -- xxx.py
    对命名有强迫症的表示严重受不鸟 T_T
    SoloCompany
        26
    SoloCompany  
       2014-02-24 11:59:13 +08:00
    @guoqiao 我也觉得应该可以单独提交,但我用 github 客户端就强制我必须要提交所有文件,然后它的界面是可以有CheckBox 选择的,我就选择了两个文件,然后点 commit 然后意外的发现另外一个没选的文件也同时 commit 了,真不知道是软件的bug还是我理解错误了
    ldc4
        27
    ldc4  
       2016-05-20 09:35:24 +08:00
    恩,看完你们的对话,了解到 checkout 是怎么区分分支和文件名了。 :p
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4742 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:52 · PVG 17:52 · LAX 02:52 · JFK 05:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.