git branch大扫除
从 http://www.joachim-breitner.de/blog/751-Spring_cleaning__local_git_branches 上看到的小技巧,觉得很棒,记录一下。
在git项目中经常会包含大量的分支,比如在在我 Linux中国 的选题仓库中就包含了一对各式各样的分支:
git branch
add-MjAxODA4MDUgV2hlcmUgVmltIENhbWUgRnJvbS5tZAo=
add-MjAxODA5MDIgTGVhcm5pbmcgQkFTSUMgTGlrZSBJdC1zIDE5ODMubWQK
add-MjAxODEwMTUgSW50ZXJuZXRzIG9mIEludGVyZXN0IC03LSBJYW4gQ29vcGVyIG9uIFRlc3QgRHJpdmVuIERldmVsb3BtZW50Lm1kCg==
add-MjAxODExMDMgSW50ZXJuZXRzIG9mIEludGVyZXN0IC04LSBUb2RkIEZlcm5hbmRleiBvbiB0aGUgbWFudWZhY3R1cmluZyBvZiBtb2Rlcm4gc2VtaWNvbmR1Y3RvcnMubWQK
add-MjAxODExMTEgSW50ZXJuZXRzIG9mIEludGVyZXN0IC05LSBKYXNvbiBTY290dCBvbiB0aGUgQ29weXJpZ2h0IEZ1cnkgUm9hZC5tZAo=
add-MjAxODExMTUgSW50ZXJuZXRzIG9mIEludGVyZXN0IC0xMC0gTWlrZSBIYXJyaXNvbiBvbiB0aGUgRWlkb3Bob3IubWQK
add-MjAxODEyMzAgSW50ZXJuZXRzIG9mIEludGVyZXN0IC0xMS0gWWVzdGVyZGF5LXMgQ29tcHV0ZXIgb2YgVG9tb3Jyb3ctIFRoZSBYZXJveCBBbHRvLm1kCg==
add-MjAxOTA0MDMgQWJzb2x1dGUgVW5pdCAodGVzdCkubWQK
add-MjAxOTA2MDUgSG93IHRvIG5hdmlnYXRlIHRoZSBLdWJlcm5ldGVzIGxlYXJuaW5nIGN1cnZlLm1kCg==
add-MjAxOTA2MTAgV2h5IGNvbnRhaW5lcnMgYW5kIEt1YmVybmV0ZXMgaGF2ZSB0aGUgcG90ZW50aWFsIHRvIHJ1biBhbG1vc3QgYW55dGhpbmcubWQK
add-MjAxOTA2MjggVW5kbyByZWxlYXNlcyBMaXZlIFJlY29yZGVyIDUuMCBmb3IgTGludXggZGVidWdnaW5nLm1kCg==
add-MjAxOTA3MDUgU3lkbmV5IEhpZ2ggUGVyZm9ybWFuY2UgR28gd29ya3Nob3AubWQK
add-MjAxOTA3MDkgUmVkIEhhdCwgSUJNLCBhbmQgRmVkb3JhLm1kCg==
add-MjAxOTA4MzAgSFBFIGludHJvZHVjZXMgVk13YXJlIHNlcnZpY2VzIG9uIEdyZWVuTGFrZS5tZAo=
add-MjAxOTA5MDIgVXNpbmcgcHJlZGljdGl2ZSBhbmFseXRpY3MgdG8gdHJvdWJsZXNob290IG5ldHdvcmsgaXNzdWVzLSBGYWN0IG9yIGZpY3Rpb24ubWQK
add-MjAxOTA5MDUgUS1BLSBIUEUtcyBuZXR3b3JraW5nIGNoaWVmIG9wZW5zIHVwIGFib3V0IGludGVsbGlnZW50IGVkZ2UsIENpc2NvIGFuZCBtaWNybyBkYXRhIGNlbnRlcnMubWQK
add-MjAxOTA5MDYgMi1NaW51dGUgTGludXggVGlwLSBUaGUgZW52IGNvbW1hbmQubWQK
add-MjAxOTA5MDkgTW92aW5nIHRvIFNELVdBTi0gQ29uc2lkZXIgU2VjdXJpdHkgQ2FyZWZ1bGx5LCBTYXkgRXhwZXJ0cyBhbmQgSVQgTWFuYWdlcnMubWQK
add-MjAxOTA5MTEgNSBXYXlzIFNELVdBTiBQcm9tb3RlIEJ1c2luZXNzIEFnaWxpdHkubWQK
add-MjAxOTA5MTEgOCBLZXkgQ29uc2lkZXJhdGlvbnMgV2hlbiBTZWxlY3RpbmcgYSBNYW5hZ2VkIFNELVdBTiBTZXJ2aWNlIFByb3ZpZGVyLm1kCg==
add-MjAxOTA5MTEgQ2lzY28gYWRkcyBzcGVlZCwgc21hcnRzIHRvIE1EUyBzdG9yYWdlIG5ldHdvcmtpbmcgZmFtaWx5Lm1kCg==
add-MjAxOTA5MTEgU0QtV0FOLSBEb2VzIFlvdXIgSVQgVGVhbSBIYXZlIFdoYXQgSXQgVGFrZXMubWQK
add-MjAxOTA5MTIgNSBNdXN0LWhhdmUgU0QtV0FOIFNlY3VyaXR5IENhcGFiaWxpdGllcy5tZAo=
add-MjAxOTA5MTIgSUJNIHoxNSBtYWluZnJhbWUsIGFtcHMtdXAgY2xvdWQsIHNlY3VyaXR5IGZlYXR1cmVzLm1kCg==
add-MjAxOTA5MTIgVG9wIDMgTWlzY29uY2VwdGlvbnMgQWJvdXQgU0QtV0FOLm1kCg==
add-MjAxOTA5MTMgR05PTUUgMy4zNCByZWxlYXNlZCAtIGNvbWluZyBzb29uIGluIEZlZG9yYSAzMS5tZAo=
add-MjAxOTA5MTMgSm9pbiBPcGVuIEphbSAyMDE5IHRvIGJ1aWxkIG9wZW4gc291cmNlIGluZGllIGdhbWVzLm1kCg==
add-MjAxOTA5MTMgV2hhdCBwb2xpdGljcyBjYW4gdGVhY2ggdXMgYWJvdXQgb3BlbiBzb3VyY2UubWQK
add-MjAxOTAyMTYgU29tZSBQcmVzZW50YXRpb24gU2xpZGVzLm1kCg==
add-MjAxOTAyMjAgSW50ZXJuZXRzIG9mIEludGVyZXN0IC0xMi0gVGVzdGluZyBNaWNoYWVsIEZlYXRoZXJzLSBQYXRpZW5jZS5tZAo=
add-MjAxOTEwMzEgRmlyZWZveCB0aXBzIGZvciBGZWRvcmEgMzEubWQK
add-MjAxOTExMTUgRmVkb3JhIHBhc3RlYmluIGFuZCBmcGFzdGUgdXBkYXRlcy5tZAo=
add-MjAxOTExMTggRmVkb3JhIHNoaXJ0cyBhbmQgc3dlYXRzaGlydHMgZnJvbSBIRUxMT1RVWC5tZAo=
add-MjAxOTExMjIgU2hhcmluZyBGZWRvcmEubWQK
add-MjAxOTExMjQgQmF1aCAtIE1hbmFnZSBTbmFwcywgRmxhdHBha3MgYW5kIEFwcEltYWdlcyBmcm9tIE9uZSBJbnRlcmZhY2UubWQK
add-MjAxOTEyMTIgNyB3YXlzIHRvIHJlbWVtYmVyIExpbnV4IGNvbW1hbmRzLm1kCg==
add-MjAxOTEyMTMgSG93IHRvIHVzZSB0aGUgTGludXggdW5pcSBjb21tYW5kLm1kCg==
add-MjAxOTEyMzEgT25lIE9mIFRoZSBSZWFzb25zIFdoeSBMaW51eCA1LjUgQ2FuIEJlIFJ1bm5pbmcgU2xvd2VyLm1kCg==
add-MjAyMDA1MDcgSG93IHRvIHJlcGVhdCBhIExpbnV4IGNvbW1hbmQgdW50aWwgaXQgc3VjY2VlZHMubWQK
add-MjAyMDAzMTAgUnVuIEt1YmVybmV0ZXMgb24gYSBSYXNwYmVycnkgUGkgd2l0aCBrM3MubWQK
* master
revert-c291cmNlcy90ZWNoLzIwMjAwNDA3IEhvdyB0byB1c2UgcHllbnYgdG8gcnVuIG11bHRpcGxlIHZlcnNpb25zIG9mIFB5dGhvbiBvbiBhIE1hYy5tZAo=
这些分支大致会处于下面几种状态:
- master分支, 指向上游的master分支
- 已经推送到remote仓库的开发分支.
- 已经发起pull request但未处理的开发分支.
- 已经发起pull request,且merge到master的开发分支
- 已经发起pull request, 且sqush或rebase到master的开发分支
- 已经发起pull request, 但被拒绝,但remote branch还在的开发分支
- 已经发起pull request, 但被拒绝,且remote branch已被删除的开发分支
- 尚未推送到remote的本地开发分支
实际上,这些分支还可以进一步合并为三类:
- master分支
- 推送到remote仓库的开发分支(remote branch或pull request)
- 未推送到remote仓库的分支
一个比较简单的方法就是使用 git branch --merged
列出所有已合并入master的本地分支然后删掉除当前分支(以* 开头的分支):
git branch --merged | egrep -v "(^\*|master)" | xargs git branch -d
不过这种方法只能删除已经merge到master的分支,其他状态的分支无法被删除,比如在我 Linux中国 的选题仓库运行 git branch --merge
的结果如下
git branch --merged |egrep -v "(^\*|master)"
add-MjAxOTA2MDUgSG93IHRvIG5hdmlnYXRlIHRoZSBLdWJlcm5ldGVzIGxlYXJuaW5nIGN1cnZlLm1kCg== add-MjAxOTA2MTAgV2h5IGNvbnRhaW5lcnMgYW5kIEt1YmVybmV0ZXMgaGF2ZSB0aGUgcG90ZW50aWFsIHRvIHJ1biBhbG1vc3QgYW55dGhpbmcubWQK
可以看到,删除的效果不佳啊。
下面是重点来了
事实上,github 上的pull request(不管是否关闭) 都对应了一个branch,通过下面操作可以将这些branch拉取下来:
修改
.git/config
在[remote "origin"]
中添加下面内容(假设你的远程repo为origin):[remote "origin"] url = … fetch = +refs/heads/*:refs/remotes/origin/* fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
- 运行
git fetch
拉去remote上的分支。
你会看到大量类似 remotes/origin/pr/XXXX
的分支
下面的事情就简单了,遍历所有remote上的分支,然后删除已经合并到该分支上的本地开发队列就行了:
for r in $(git branch -r --format='%(refname)'); do git branch --merged $r; done | sort -u | grep -v '^\*' | xargs -r git branch -D
当然,你也很容易发现,若远程仓库pull request特别多,那么这个循环操作也会比较慢。