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

[Git]你们怎么恢复已删除的commit?

  •  
  •   pythonee · 2013-03-30 11:06:21 +08:00 · 7242 次点击
    这是一个创建于 4051 天前的主题,其中的信息可能已经有所发展或是发生改变。
    比如我用 rebase -i 合并两个commit,然后删除一个commit。成功后,我又想把刚刚那个commit加回来呢?

    可能实际中没有人这么玩,而且那个commit必须不和其他commit有冲突可能才玩的转。但是我觉得git是全量保存,那么应该是可以做到,而且居然有commit记录,理应上是可以恢复任何东西。我想到的一个办法是reset,但觉得不好,不知道大家会怎么做。
    16 条回复    1970-01-01 08:00:00 +08:00
    jsz
        1
    jsz  
       2013-03-30 11:12:05 +08:00   ❤️ 1
    git reflog

    reset 到两个commit都没有的状态,然后再 cherry-pick 回来。
    pythonee
        2
    pythonee  
    OP
       2013-03-30 11:24:46 +08:00
    @jsz 哦? 我还没有用过cherry-pick,不晓得cherry-pick回来之后,所有后续commit是否都还在,还是说仅仅到reset的那个commit
    jsz
        3
    jsz  
       2013-03-30 11:33:57 +08:00   ❤️ 1
    @pythonee cherry-pick 只是拿指定的那些commit.

    假设你是把 A B 两个 commit rebase 成了一个 C。那么,

    git reset --hard HEAD^ 把 C 删除
    git cherry-pick A B 把 A B 拿回来
    pythonee
        4
    pythonee  
    OP
       2013-03-30 11:59:05 +08:00
    @jsz 嗯,实际操作了一把,但是这样离我想达到的效果还是有差距的,我还想保留commit的时间顺序

    举个例子,现在我的commit是这样

    A --> B --> C --> D

    rebase后,我把B删掉了,现在是

    A --> C --> D

    而我想恢复B commit,还想把B放到A之前,C之后,也就是像原来一样

    如果用cherry-pick,我觉得如果没有冲突的话,我可以直接cherry-pick回来,也就是

    A --> C -->D

    如果有冲突,大不了reset到A,然后一步一步cherry-pick回来,但是这样比较没有效率就是
    pythonee
        5
    pythonee  
    OP
       2013-03-30 12:02:04 +08:00
    更正:

    如果用cherry-pick,我觉得如果没有冲突的话,我可以直接cherry-pick回来,也就是

    A --> C -->D --> B
    rorvn
        6
    rorvn  
       2013-03-30 12:21:09 +08:00
    @pythonee 删掉还要找回来,你删他干嘛。
    checkout回去,重新rebase吧……
    pythonee
        7
    pythonee  
    OP
       2013-03-30 16:07:52 +08:00
    @rorvn 呵呵,说了实际使用可能不这样,我只是想Git也能做到并且这样也是熟悉Git的一种方式
    imcotton
        8
    imcotton  
       2013-03-30 19:05:55 +08:00
    imcotton
        9
    imcotton  
       2013-03-30 19:06:35 +08:00
    G_virus
        10
    G_virus  
       2013-03-31 01:20:06 +08:00 via iPhone
    用reflog找到最初的D,reset回到D就可以了。git的commit包含了整个历史,只要HEAD对就对了。
    pythonee
        11
    pythonee  
    OP
       2013-03-31 17:10:51 +08:00
    @G_virus 你是说先reset到A,然后cherry-pick B,最后reset到D对吗
    jsz
        12
    jsz  
       2013-03-31 21:12:23 +08:00 via Android
    @pythonee 咱们说的好像是一个意思?就是reset到A,然后把后边的一次cherrypick回来。cherrypick可以一下指定多个commit,我可能把顺序说反了。
    jsz
        13
    jsz  
       2013-03-31 21:13:18 +08:00 via Android
    把后边的”依次”*
    pythonee
        14
    pythonee  
    OP
       2013-03-31 21:48:52 +08:00
    @jsz 嗯,通常这种情况是在不冲突的时候才能玩的转,后面想想,我不reset到A,直接在D之后cherry-pick,然后再rebase也行。谢谢你的回复
    jsz
        15
    jsz  
       2013-04-01 13:30:35 +08:00
    @pythonee 也可以先 rebase -i,然后选择编辑 A,然后 cherry-pick B,然后 rebase --continue。
    G_virus
        16
    G_virus  
       2013-04-03 11:56:25 +08:00
    @pythonee 不是。简单地说,git的commit包含两方面信息,一是源代码的内容(我们最关心的),二是指向父commit的指针。rebase之后,C的父指针是A而不是B,已经不是的当初的C了,姑且称之为C',同样的,D'的父指针是C',所以也不是当初的D了。如果你只是想恢复成最初的A->B->C->D,那只需要用reflog找到“当初”的D,reset到那个点上就可以了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2267 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 06:24 · PVG 14:24 · LAX 23:24 · JFK 02:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.