V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
cielpy
V2EX  ›  iDev

Xcode 合并冲突后 Discard All Changes 导致代码丢失问题

  •  
  •   cielpy ·
    EkkoG · 2017-10-15 22:10:12 +08:00 · 5435 次点击
    这是一个创建于 2356 天前的主题,其中的信息可能已经有所发展或是发生改变。
    https://imciel.com/2017/10/13/xcode-discard-change-and-git-merge-issue/

    最近被这个问题坑的不轻,就写了下来,大家可以看看避免踩同样的坑
    13 条回复    2017-10-17 23:47:36 +08:00
    msg7086
        1
    msg7086  
       2017-10-16 04:48:14 +08:00
    这就是为什么我一直建议重度 Git 使用者挑选一个顺手的强大的 GUI。
    alang
        2
    alang  
       2017-10-16 06:14:37 +08:00 via iPhone
    必须命令行啊,gui 都是不靠谱的
    xpol
        3
    xpol  
       2017-10-16 08:40:42 +08:00
    Sourcetree 党表示 GUI 是必须的。
    xpol
        4
    xpol  
       2017-10-16 08:47:59 +08:00
    怎么可能丢失代码?

    合并前都是要求当前分支无变更啊(包括不能有 stage 代码)。
    这就意味着要么你提交了,要么你 stash 了。

    随便 discard 啊。原来的代码不在分支上就在 stash 里面啊。

    看了一下链接,原来是带着 stage 但是未 commit 代码合并……
    别怪工具,怪用工具的人,下次记得在干净的工作目录里面合并。
    cielpy
        5
    cielpy  
    OP
       2017-10-16 22:46:34 +08:00   ❤️ 1
    @xpol

    文章最后有 demo,有空的话你可以试一下

    stage 是空的

    合并前是这样的

    https://i.loli.net/2017/10/16/59e4c5a94bd96.png

    若有幸是刚打开 SourceTree

    合并后再 Discard 是这样的

    https://i.loli.net/2017/10/16/59e4c26462ecf.png

    可以看到 commit 输入框有内容,能引起注意

    若是已经用 SourceTree commit 过,并停留在 commit 后的界面没动,合并后是这样的

    https://i.loli.net/2017/10/16/59e4c32cf2bcb.png

    Discard 后是这样的

    https://i.loli.net/2017/10/16/59e4c369d9b3a.png

    修改后是这样的

    https://i.loli.net/2017/10/16/59e4c5004c2d2.png

    commit 后是这样的

    https://i.loli.net/2017/10/16/59e4c50048381.png

    请问最后一次 commit 哪里可以看出来有别的东西合并进来了
    cielpy
        6
    cielpy  
    OP
       2017-10-16 22:53:38 +08:00
    @msg7086
    @alang
    @xpol

    我个人觉得各有各的优势,GUI 在查看历史记录合并历史等等操作的时候比较直观,命令行强在各种功能组合,如果理解每一个选项的作用,一个命令的效果是比 GUI 鼠标点起来更直观,GUI 不够透明,不知道做了什么隐藏的操作,对仓库有什么影响,不过刚发现 SourceTree 的命令历史,这方面的缺陷可以查看命令弥补,我是配置用的,大部分操作用命令,偶尔用 SourceTree 查看历史记录,切换分支之类的
    msg7086
        7
    msg7086  
       2017-10-17 06:21:24 +08:00
    @cielpy 我自己是用的 SmartGit,而且我在我司团队里推广使用过,效果很好。
    GUI 是不够透明,不过幸好 SmartGit 里几乎所有的操作都会在 Log 里打出使用过的命令,有些时候我甚至是在跟着 GUI 学 Git。
    如果只是轻度使用 Git 的话倒是无所谓,我对源代码管理要求比较高,Branching Rebasing Merging 非常频繁,而且要求 Interactive Rebase 整理源代码历史记录以方便后期 Blame 和 Revert,没有 GUI 感觉是如履薄冰。
    cielpy
        8
    cielpy  
    OP
       2017-10-17 09:41:04 +08:00
    @msg7086 嗯嗯,根据使用场景选合适的工具就好啦
    xpol
        9
    xpol  
       2017-10-17 20:40:36 +08:00
    没有验证过 Xcode 里面的 Discard all changes 做了哪些操作。但是放弃 merge 的正确的命令行应该是 git merge --abort ( git > 1.7.4 https://stackoverflow.com/questions/5741407/how-to-undo-a-git-merge-with-conflicts ) 。

    我看了一下 demo,了解了:

    1. 当前在 master,将 test 合并过来
    2. 合并发现冲突
    3. 用 Xcode 的 Discard all changes 或者 git reset --hard HEAD,重置 index 和 working copy 到 HEAD 的状态(即 master 分支在合并前的状态,也就是 demo 中 test 0 这个提交的状态)
    4. 提交,由于当前还处于 merge 状态,所以这个提交的状态被当成合并后结果

    简言之,由于 Xcode 的 Discard all changes 或者命令行的 git reset --hard HEAD 都终止 merge 状态。稍后的提交会被当成合并的结果。
    xpol
        10
    xpol  
       2017-10-17 20:44:22 +08:00
    你可以本地退回到 master 上的 test 0 这个版本,然后和 test 上的 test 2 版本进行合并,然后选择 test 2 的版本,然后提交。最后 git push origin +master 强制 push。
    xpol
        11
    xpol  
       2017-10-17 21:05:55 +08:00
    另外,代码并没有丢失。正确的版本依然安安静静地躺在 test 分支上。

    问题的根源是下面这一个错误的认识:

    『若想丢弃此次合并,可以使用命令重置,回到当前分支的 HEAD,命令如下:git reset --hard HEAD 』

    正确的认识是:

    若想丢弃此次合并,可以使用命令放弃合并,命令如下:

    git merge --abort,

    或者 Sourcetree 里面选中合并前当前分支合并前的版本 -> 右键 -> Reset <branch_name> to this commit -> using mode 选择 hard 』
    xpol
        12
    xpol  
       2017-10-17 21:39:01 +08:00
    @cielpy 我是来认错的。我上一条关于 git reset --hard HEAD 不能放弃合并的说法才是错误的,对不起~~

    根据 https://git-scm.com/book/tr/v2/Git-Tools-Advanced-Merging 的描述 git reset --hard HEAD 确实也可以用来放弃合并。

    你说的对,应该只是 Xcode 中的 Discard all changes 不能放弃合并。
    cielpy
        13
    cielpy  
    OP
       2017-10-17 23:47:36 +08:00
    @xpol 根据实际操作结果来看的话,git reset --hard HEAD 是会放弃合并的,而 Discard all changes 不会,造成了这个问题

    当然我说的「代码丢失」意思其实不是真正的丢了,因为 commit 记录还在嘛,只是在合并后的分支上,看不到了这个 commit 相关的修改的一种异常状态
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5878 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 39ms · UTC 02:19 · PVG 10:19 · LAX 19:19 · JFK 22:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.