I would like to start writing more here about general Git tips, tricks and upcoming features. There has actually been a lot of cool stuff that has happened since the book was first published, and a number of interesting things that I didn't get around to covering in the book. I figure if I start blogging about the more interesting stuff, it should serve as a pretty handy guide should I ever start writing a second edition.

For the first such post, I'm going to cover a topic that was asked about at a training I did recently. The question was about a workflow where long running branches are merged occasionally, much like the Large Merging workflow that I describe in the book. They asked how to unmerge a branch, either permenantly or allowing you to merge it in later.

You can actually do this a number of ways. Let's say you have history that looks something like this:

You have a couple of topic branches that you have developed and then integrated together by a series of merges. Now you want to revert something back in the history, say 'C10' in this case.

The first way to solve the problem could be to rewind 'master' back to C3 and then merge the remaining two lines back in again. This requires that anyone you're collaborating with knows how to handle rewound heads, but if that's not an issue, this is a perfectly viable solution. This is basically how the 'pu' branch is handled in the Git project itself.

$ git checkout master
$ git reset --hard [sha_of_C3]
$ git merge jk/post-checkout
$ git merge db/push-cleanup

Once you rewind and remerge, you'll instead have a history that looks more like this:

Now you can go back and work on that newly unmerged line and merge it again at a later point, or perhaps ignore it entirely.

Reverting a Merge

However, what if you didn't find this out until later, or perhaps you or one of your collaborators have done work after this merge series? What if your history looks more like this:

Now you either have to revert one of the merges, or go back, remerge and then cherry-pick the remaining changes again (C10 and C11 in this case), which is confusing and difficult, especially if there are a lot of commits after those merges.

Well, it turns out that Git is actually pretty good at reverting an entire merge. Although you've probably only used the git revert command to revert a single commit (if you've used it at all), you can also use it to revert merge commits.

All you have to do is specify the merge commit you want to revert and the parent line you want to keep. Let's say that we want to revert the merge of the jk/post-checkout line. We can do so like this:

$ git revert -m 1 [sha_of_C9]
Finished one revert.
[master 88edd6d] Revert "Merge branch 'jk/post-checkout'"
1 files changed, 0 insertions(+), 2 deletions(-)

That will introduce a new commit that undoes the changes introduced by merging in the branch in the first place - sort of like a reverse cherry pick of all of the commits that were unique to that branch. Pretty cool.

However, we're not done.

Reverting the Revert

Let's say now that you want to re-merge that work again. If you try to merge it again, Git will see that the commits on that branch are in the history and will assume that you are mistakenly trying to merge something you already have.

$ git merge jk/post-checkout
Already up-to-date.

Oops - it did nothing at all. Even more confusing is if you went back and committed on that branch and then tried to merge it in, it would only introduce the changes since you originally merged.

Gah. Now that's really a strange state and is likely to cause a bunch of conflicts or confusing errors. What you want to do instead is revert the revert of the merge:

$ git revert 88edd6d
Finished one revert.
[master 268e243] Revert "Revert "Merge branch 'jk/post-checkout'""
1 files changed, 2 insertions(+), 0 deletions(-)

Cool, so now we've basically reintroduced everything that was in the branch that we had reverted out before. Now if we have more work on that branch in the meantime, we can just re-merge it.

$ git merge jk/post-checkout
Auto-merging test.txt
Merge made by recursive.
test.txt | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

So, I hope that's helpful. This can be particularly useful if you have a merge-heavy development process. In fact, if you work mostly in topic branches before merging for integration purposes, you may want to use the git merge --no-ff option so that the first merge is not a fast forward and can be reverted out in this manner.

Until next time.

https://git-scm.com/blog/2010/03/02/undoing-merges.html

git 撤销 merging,git取消merge

$ git pull origin test
// git pull合并代码的时候,若发生冲突,会处于merging状态,检查代码,发现自己的分支低于主分支,这个时候想撤销merge

// 撤销merge
$ git reset --hard HEAD (or sha_1)

用git提交代码时 冲突了

于是分支名变成如下图所示

在命令行输入:

git reset --hard head 就可以了

但是在这个过程中 可能会碰到一个问题,如下图:

这个意思是在C:\Users\Admin\git\phhhh\.git目录下已经有一个index.lock文件夹存在了,只需要去这个目录下删了这个文件夹,然后再输入 git reset --hard head 就ok了

 http://blog.csdn.net/Android_Amelia/article/details/49612631?locationNum=11&fps=1

Undoing Merges的更多相关文章

  1. git push 报错:you are not allowed to upload merges

    git rebase Cannot rebase: You have unstaged changes. git stash # 每次 push 前 git pull --rebase git pus ...

  2. Please enter a commit message to explain why this merge is necessary, # especially if it merges an updated upstream into a topic branch. # # Lines starting with '#' will be ignored, and an empty messa

    1.git提交的时候遇到: # Please enter the commit message for your changes. Lines starting with '#' will be ig ...

  3. Devexpress VCL Build v2014 vol 15.2.3 发布

    2016年第一个版本,继续修补. New Major Features in 15.2 What's New in VCL Products 15.2 Breaking Changes To lear ...

  4. TortoiseSVN中图标的含义

    今天在使用svn时发现有好多不认识了,所以查了下svn帮助手册.借此总结了下 svn 中图标的含义 一个新检出的工作复本使用绿色的勾做重载.表示Subversion状态 正常. 在开始编辑一个文件后, ...

  5. Bash,Vim,gdb&git常用命令

    Bash 目录 pwd  //查看当前目录 mkdir dir1 dir2  //创建目录 tree dir1 mv test1.cpp test2.cpp dir1 dir  //移动文件/目录到目 ...

  6. Pro Git - 笔记2

    Git Basics Getting a Git Repository Initializing a Repository in an Existing Directory For Linux: $ ...

  7. TortoiseSVN 日常操作指南

    TortoiseSVN A Subversion client for Windows Stefan Küng Lübbe Onken Simon Large 2005/01/17 19:09:21 ...

  8. InnoDB关键特性学习笔记

    插入缓存 Insert Buffer Insert Buffer是InnoDB存储引擎关键特性中最令人激动与兴奋的一个功能.不过这个名字可能会让人认为插入缓冲是缓冲池中的一个组成部分.其实不然,Inn ...

  9. 自己写jquery插件之模版插件高级篇(一)

    需求场景 最近项目改版中,发现很多地方有这样一个操作(见下图gif动画演示),很多地方都有用到.这里不讨论它的用户体验怎么样. 仅仅是从复用的角度,如果每个页面都去写text和select元素,两个b ...

随机推荐

  1. 中国象棋游戏Chess(3) - 实现走棋规则

    棋盘的绘制和走棋参看博文:中国象棋游戏Chess(1) - 棋盘绘制以及棋子的绘制,中国象棋游戏Chess(2) - 走棋 现在重新整理之前写的代码,并且对于每个棋子的走棋规则都进行了限制,不像之前那 ...

  2. Git错误一例

    Bitbucket一直不稳定,push, pull经常失效.幸好还有goagent可以用. 把git的全局配置改为走goagent代理,可以正常使用: [http] proxy = http://12 ...

  3. 更改EBS服务器域名/IP

    more: 341322.1 : How to change the hostname of an Applications Tier using AutoConfig 338003.1 : How  ...

  4. Mybatis 源码之Plugin类解析

    public class Plugin implements InvocationHandler { private Object target; //目标对象 private Interceptor ...

  5. Treemap 有序的hashmap。用于排序

    TreeMap:有固定顺序的hashmap.在需要排序的Map时候才用TreeMap. Map.在数组中我们是通过数组下标来对其内容索引的,键值对. HashMap HashMap 用哈希码快速定位一 ...

  6. java--字符编码,正则表达式

    转载请申明出处:http://blog.csdn.net/xmxkf day21   字符编码 06-IO流(转换流的字符编码) 字符编码: 1. 字符流的出现为了方便操作字符,更重要的是加入了编码转 ...

  7. vue2.0-基于elementui换肤[自定义主题]

    0. 直接上 预览链接 vue2.0-基于elementui换肤[自定义主题] 1. 项目增加主题组件 在项目的src/components下添加skin文件夹 skin文件获取地址 2. 项目增加自 ...

  8. MySQL中的行级锁,表级锁,页级锁

    在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在数据库的锁机制中介绍过,在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引 ...

  9. JavaScript脚本放在哪里

    在HTML body部分中的JavaScripts会在页面加载的时候被执行. 在HTML head部分中的JavaScripts会在被调用的时候才执行. ----------------------- ...

  10. 简单工厂,Factory Method(工厂方法)和Abstract Factory(抽象工厂)模式

    对于简单工厂来说,它的工厂只能是这个样子的 public class SimplyFactory {  /** * 静态工厂方法 */ public static Prouct factory(Str ...