Github cherrry-pick 工具。
解决在一个分支提交一个Commit 需要提交到其它分支的需要。特别是在分支超级多的情况下。
#!/usr/bin/python3
# Filename: git_cherry.py
# Apply a commit for all branch in a git repo.
# :param workspace: The git repo dict.
# :param cherry_pick_name: The cherry-pick commit id.
# :param pattern_branch: The regex pattern, for filter which you want to apply cherry-pick branch.
# :param filter_branch_names: the branch name's which you don't want to apply cherry-pick. This is a list.
# Notes: value must be full branch name.
#
# use example:
# [workspace] [cherry_pick_name] [pattern_branch] [filter_branch_names]
# python3 git_cherry.py ./ e350he "remotes" "remotes/origin/master"
#
# @Author: Alex Liu
# @Email: quenlenliu@gmail.com
#
import subprocess
import os
import sys
def get_all_branch(pattern):
"""
Get all branch which match the pattern in current work direction.
:param pattern: str
:return: list
"""
(status, output) = subprocess.getstatusoutput("git branch -a | grep \"" + pattern + "\"")
branch_list = output.splitlines()
result = []
for str in branch_list:
str = str[2:].split(' ')[0]
result.append(str)
return result
def checkout_branch(branch_name=""):
"""
Checkout and pull a branch.
If branch name is a remote branch, its content must be like this "remotes/origin/master"
In this case: this will try to checkout a local branch if without has a local branch
and track remotes branch. if already has a local branch, just checkout it
and pull from this remotes branch.
if branch is a local branch: checkout it and pull it.
:param branch_name:
:return:
"""
branch_detail = branch_name.split('/')
if len(branch_detail) == 3:
(status, output) = subprocess.getstatusoutput("git checkout -t " + branch_name)
print(output)
if status != 0:
(status, output) = subprocess.getstatusoutput("git checkout " + branch_detail[2])
print(output)
subprocess.getstatusoutput("git pull " + branch_detail[1] + " " + branch_detail[2])
print(branch_name + ": " + str(status) + " " + output)
else:
(status, output) = subprocess.getstatusoutput("git checkout " + branch_name)
print(branch_name + ": " + str(status) + " " + output)
subprocess.getstatusoutput("git pull ")
return 0
def apply_cherry_pick(cherry_pick_name):
(status, output) = subprocess.getstatusoutput("git cherry-pick " + cherry_pick_name)
print(str(status) + " " + output)
return status
def submit_branch(branch_name):
branch_detail = branch_name.split('/')
if len(branch_detail) == 3:
(status, output) = subprocess.getstatusoutput("git push " + branch_detail[1] + " " + branch_detail[2])
print(branch_name + ": " + str(status) + " " + output)
return status
return -1
def is_status_ok(status=0):
if status == 0:
return True
else:
# return true now, don's check
return True
def apply_patch_for_all_branch(workspace="", cherry_pick_name="", pattern_branch="remotes", filter_branch_names=[]):
"""
Apply a patch for branches in a git repo.
:param workspace: the dir of the git repo. Type: str
:param pattern_branch: the dest branch pattern. Type: str
:param cherry_pick_name: the commit id which your want apply for other branch. Type: str
:param filter_branch_names: The branch names which you do not want applied branch. Type: list.
:return:
"""
print("--------------------------------------")
print("------- Start apply cherry-pick ------")
os.chdir(workspace)
print("Workspace: " + os.getcwd())
cherry_pick_commit = cherry_pick_name
print("Apply cherry-pick for All branch : " + cherry_pick_commit)
print("Filter Branches: " + str(filter_branch_names))
print("Pattern Branch: " + pattern_branch)
all_branches = get_all_branch(pattern_branch)
print("Check Branches: ")
print(all_branches)
for branch_name in all_branches:
if branch_name not in filter_branch_names:
print("\n\n")
print("Start Apply Branch --------------: " + branch_name)
status = checkout_branch(branch_name)
if is_status_ok(status):
status = apply_cherry_pick(cherry_pick_commit)
if is_status_ok(status):
status = submit_branch(branch_name)
if is_status_ok(status):
print("Apply pick for branch " + branch_name + " Success")
else:
print("Apply pick for branch " + branch_name + " Error")
return
else:
print("Apply pick for branch " + branch_name + " Error")
return
else:
print("Apply pick for branch " + branch_name + " Error")
return
print("------- End apply cherry-pick ---------")
print("---------------------------------------")
def execute():
workspace = sys.argv[1]
cherry_pick_name = sys.argv[2]
pattern_branch = sys.argv[3]
filter_branch_names = sys.argv[4:]
apply_patch_for_all_branch(workspace, cherry_pick_name, pattern_branch, filter_branch_names)
if __name__ == "__main__":
execute()