Undoing Merges
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了
Undoing Merges的更多相关文章
- 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 ...
- 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 ...
- 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 ...
- TortoiseSVN中图标的含义
今天在使用svn时发现有好多不认识了,所以查了下svn帮助手册.借此总结了下 svn 中图标的含义 一个新检出的工作复本使用绿色的勾做重载.表示Subversion状态 正常. 在开始编辑一个文件后, ...
- Bash,Vim,gdb&git常用命令
Bash 目录 pwd //查看当前目录 mkdir dir1 dir2 //创建目录 tree dir1 mv test1.cpp test2.cpp dir1 dir //移动文件/目录到目 ...
- Pro Git - 笔记2
Git Basics Getting a Git Repository Initializing a Repository in an Existing Directory For Linux: $ ...
- TortoiseSVN 日常操作指南
TortoiseSVN A Subversion client for Windows Stefan Küng Lübbe Onken Simon Large 2005/01/17 19:09:21 ...
- InnoDB关键特性学习笔记
插入缓存 Insert Buffer Insert Buffer是InnoDB存储引擎关键特性中最令人激动与兴奋的一个功能.不过这个名字可能会让人认为插入缓冲是缓冲池中的一个组成部分.其实不然,Inn ...
- 自己写jquery插件之模版插件高级篇(一)
需求场景 最近项目改版中,发现很多地方有这样一个操作(见下图gif动画演示),很多地方都有用到.这里不讨论它的用户体验怎么样. 仅仅是从复用的角度,如果每个页面都去写text和select元素,两个b ...
随机推荐
- Android Studio使用Lint进行代码检查
Android Studio目前已经更新到1.4版本,它作为Google官方推荐的IDE,功能非常强大,其中提供了一套静态代码分析工具,它可以帮助我们检查项目中存在的问题,让我们更有规范性的开发App ...
- GROUP BY,WHERE,HAVING间的区别和用法
having子句与where都是过滤语句. where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,条件中不能包含聚组函数,使用where条件显示特定的行 ...
- CIO必看:跨国集团采购部报表系统的建设经验分享
CIO必看:跨国集团采购部报表系统的建设经验分享 引言 福耀集团是国内最具规模.技术水平最高.出口量最大的汽车玻璃生产供应商,产品"FY"商标是中国汽车玻璃行业第一个"中 ...
- Android特效专辑(一)——水波纹过渡特效(首页)
Android特效专辑(一)--水波纹过渡特效(首页) 也是今天看到的一个特效,感觉挺漂亮的,最近也一直在筹划一个APP,就想把他当做APP的首页,然后加些处理,关于首页APP的特效等我完工了再贴出来 ...
- HDFS APPEND性能测试
hbase在写入数据之前会先写hlog,hlog目前是sequencefile格式,采用append的方式往里追加数据.之前团队的同学测试关闭hlog会一定程序上提升写hbase的稳定性.而在我之前的 ...
- Android为什么使用Binder-android学习之旅(101)
基础知识 Android进程和linux进程一样,他们只运行在进程固有的虚拟空间中.一个4GB的虚拟地址空间,其中3GB是用户空间,1GB是内核空间 ,用户空间是非共享的,内核空间是共享的,如下图: ...
- 自制node.js + npm绿色版
自制node.js + npm绿色版 Node.js官网有各平台的安装包下载,不想折腾的可以直接下载安装,下面说下windows平台下如何制作绿色版node,以方便迁移. 获取node.exe下载 ...
- 每天几分钟跟小猫学前端之node系列:用node实现最简单的爬虫
先来段求分小视频: https://www.iesdouyin.com/share/video/6550631947750608142/?region=CN&mid=6550632036246 ...
- 大型B2C网站高性能可伸缩架构技术探秘
大型B2C网站高性能可伸缩架构技术探秘 2010-07-21 08:51 狂放不羁 JavaEye 字号:T | T 向您介绍大型B2C网站高性能的网站架构技术,包括缓存的使用.应用程序和数据库的拆分 ...
- JS基础:闭包和作用域链
简介 一个定义在函数内部的函数与包含它的外部函数构成了闭包,内部函数可以访问外部函数的变量,这些变量将一直保存在内存中,直到无法再引用这个内部函数. 例如: var a = 0; function o ...