git checkout -- file 时能否自动备份一下修改过的文件? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
guoqiao
V2EX    程序员

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

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

    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     Solana     2980 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 37ms UTC 14:18 PVG 22:18 LAX 07:18 JFK 10:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86