假设你的历史记录为
$ git lola
* 6473d7f (master) 更新
| * 9bcfa7e (HEAD, topic) 修改 a、b 和 c
| * 99af942 修改 b 和 c
| * 8383e2c 修改 a 和 b
|/
* d1363f4 基准线
注意:lola
是一个非标准但有用的别名。
这些提交修改了三个不同的文件。
$ git log --decorate=short --pretty=oneline --name-status topic
9bcfa7e946a92c226ad50ce430a9e4ae55b32490 (HEAD, topic)
M a
M b
M c
99af942dbb922effcad8a72e96bec9ee9afcc437 修改 b 和 c
M b
M c
8383e2c8d6092550fec13d3c888c037b3a68af15 修改 a 和 b
M a
M b
d1363f4fba67d94999b269b51bdb50a8a68ba27a 基准线
A a
A b
A c
您想保留对文件 b
的更改,并且要丢弃所有对 a
和 c
的更改。使用 git filter-branch
可以实现这一点。
$ git checkout -b tmp topic
切换到新分支“tmp”
$ git merge-base topic master
d1363f4fba67d94999b269b51bdb50a8a68ba27a
$ git filter-branch --tree-filter 'git checkout d1363f -- a c' master..tmp
重写 8383e2c8d6092550fec13d3c888c037b3a68af15 (1/3)
重写 99af942dbb922effcad8a72e96bec9ee9afcc437 (2/3)
重写 9bcfa7e946a92c226ad50ce430a9e4ae55b32490 (3/3)
参考 'refs/heads/tmp' 被重写
上述的树过滤器检查了指定范围内的提交并将文件 a
和 c
恢复到所谓的“合并基础”内容,也就是 topic
分支与 master
分支分离时的提交。
现在,tmp
分支拥有 topic
对 b
的所有更改,但没有对其他任何文件的更改。
$ git log --decorate --pretty=oneline --name-status tmp
9ee7e2bd2f380cc338b0264686bcd6f071eb1087 (HEAD, tmp) 修改 a、b、c
M b
226c22f150af1ddc1f9adc19f97fc4f220851ada 修改 b 和 c
M b
45e706f7b22c37ee2025ee0d04c651135e7b31cd 修改 a 和 b
M b
d1363f4fba67d94999b269b51bdb50a8a68ba27a 基准
A a
A b
A c
作为安全措施,git filter-branch
会存储原始引用的备份。当您满意更改并想要删除备份 tmp
时,请运行以下命令:
$ git update-ref -d refs/original/refs/heads/tmp
git reflog
或git for-each-ref
以获取旧分支的SHA-1。使用git checkout -b old refs/original/refs/heads/tmp
或git checkout -b $sha1
复活旧分支。 - Greg Bacon