可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want to make a single commit on different branches at the same time, since, in my project, I have different branches for different clients.
Say, I have made a new feature commit on Branch A. Can I also make this commit on Branch B, Branch C and D at the same time as well? Is there any short cut command for this? This is very troublesome to checkout one branch, and cherrypick the commit everytime, sometime, if the commit is necessary on many branches, it would be a nightmare for me.
Any simple bash script for this operation?
There is a similar question in there. but rebasing is not that I want.
回答1:
The cherry-pick feature will do the job and will only apply the last commit:
Considering branches A, B
git checkout A
git commit -m "Fixed the bug x"
git checkout B
git cherry-pick A
hope this helps!
回答2:
Since there is no typical answer for my question, I have written a simple script to automate this process. Feel free to comment this code.
#!/bin/bash
BRANCHES=(
master_branch
develop_branch
testing_branch
)
ORIGINALBRANCH=`git status | head -n1 | cut -c13-`
git commit -m $1
CHERRYCOMMIT=`git log -n1 | head -n1 | cut -c8-`
for BRANCH in "${BRANCHES[@]}";
do
git stash;
git checkout $BRANCH;
git cherry-pick $CHERRYCOMMIT;
git checkout $ORIGINALBRANCH;
git stash pop;
done
回答3:
Something you might want to have a look at: git stash
your changes, git commit
, git checkout
another branch, git stash apply
, git commit
, etc.
See the man pages.
回答4:
I think you can write a post-commit hook to merge or cherry-pick with the other branches. But it will of course not be a single commit.
Hook will automatize what you want to achieve.
http://git-scm.com/docs/githooks
回答5:
Maybe this will help some people,
I used the "Kit Ho"s method above and added it to .gitconfig as alias.
; commitall commits to the current branch as well the all the branches mentionedin BRANCHES array var as shown below.
commitall = "!f() { \
BRANCHES=( \
branches1 \
branches2 \
); \
usage() \
{ \
echo \"Usage: git commitall -m 'JIRA: BRANCHNAME:<comment to check in>'\"; \
exit 1; \
}; \
OPTIND=1; \
DFNs=\"\"; \
while getopts \"h:m:\" opt; \
do \
case \"$opt\" in \
h) \
usage; \
;; \
m) export Comment=$OPTARG; \
;; \
esac; \
done; \
ORIGINALBRANCH=`git symbolic-ref HEAD|cut -d/ -f3- `; \
echo \"Current branch is $ORIGINALBRANCH \" ; \
echo $Comment | grep \"^JIRA: $ORIGINALBRANCH:\" > /dev/null 2>&1 ; \
if [ $? -ne 0 ]; then \
usage; \
fi; \
LOGMSG=`git log -1 --pretty=%B --grep=\"JIRA: $ORIGINALBRANCH:\" `; \
MSG='commit first time in this branch is a success' ; \
if [ \"$LOGMSG\" == \"\" ]; then \
git commit -m \"$Comment\"; \
else \
git commit -a --amend -C HEAD; \
MSG='commit with amend succeeded' ; \
fi; \
if [ $? -ne 0 ]; then \
echo \"git commit failed!\"; \
exit 1; \
else \
echo \"$MSG\" ; \
fi; \
CHERRYCOMMIT=`git log -n1 | head -n 1 | cut -c8- ` ; \
if [ \"$CHERRYCOMMIT\" == \"\" ]; then \
echo \"'git log -n1 | head -n 1 | cut -c8-' no commits for this branch\"; \
exit 1; \
fi; \
echo \"found this commit -> $CHERRYCOMMIT for current branch\"; \
stashes=`git stash list | grep \"WIP on $ORIGINALBRANCH\" ` ; \
for BRANCH in \"${BRANCHES[@]}\"; do \
if [ \"$stashes\" ]; then \
git stash; \
fi;\
git checkout $BRANCH; \
if [ $? -ne 0 ]; then \
echo \"git checkout $BRANCH failed!\"; \
exit 1; \
fi; \
git cherry-pick $CHERRYCOMMIT; \
git checkout $ORIGINALBRANCH; \
if [ \"$stashes\" ]; then \
git stash pop; \
fi; \
done; \
}; \
f"
回答6:
No, I don't think you can do this. Your best option would be to commit to one of your branches (or a master branch) and then either merge the commit into the others one by one, or cherry-pick the commit into each of the other branches.
回答7:
I don't think there is a way to that. Maybe you need to write a bash script for it or make a different repo for different branches.
回答8:
You can also do nice automation using some Python:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Populate specified or latest commit across all branches in the repository.
"""
import os
import re
import sys
import sh
git = sh.git.bake(_cwd=os.curdir)
if len(sys.argv) > 1:
if '-h' in sys.argv or '--help' in sys.argv:
print('Usage: git-populate.py [commit] [-h|--help]')
sys.exit(0)
else:
commit = sys.argv[1]
else:
# By default choose latest commit.
git_log = git('--no-pager', 'log', '-n', '1', '--no-color').stdout
commit = re.search(r'[a-f0-9]{40}', git_log).group()
print('Commit to be populated: {0:.6s}'.format(commit))
git_branch = git.branch('-a', '--no-color').stdout
source_branch = re.search(r'\*\s(\w+)$', git_branch, re.MULTILINE).group(1)
print('Source branch: {0}'.format(source_branch))
branches = re.findall(r'remotes/\w+/([\w-]+)$', git_branch, re.MULTILINE)
# Exclude current branch from target branches.
branches = [i for i in branches if i != source_branch]
print('Target branches: {0}'.format(branches))
print('Stashing local changes')
git_stash = git.stash().stdout
for branch in branches:
print('Ading commit {0:.6s} to branch {1}'.format(commit, branch))
git.checkout(branch)
try:
result = git('cherry-pick', commit)
except sh.ErrorReturnCode_1:
# Ignore diplicate cherry pick and discard changes.
git.reset()
git.checkout(source_branch)
print('Return to branch {0}'.format(source_branch))
if not git_stash.startswith('No local changes to save'):
print('Restoring local changes')
git.stash.pop()
回答9:
It might depend on how you are going to push your commits. I mean you always have the chance to push into multiple branches with one git push
command.
Do the following .git/config
settings to ensure that the master
branch will always be pushed to the foobar
branch, too.
[remote "origin"]
url = git@github.com:mgerhardy/example.git
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/heads/master
push = refs/heads/master:refs/heads/foobar
But the problem here might be that if these two branches diverged, you can't push to them. You still could reorganize your code that you client detection is based on the branch you are building. That way you could maintain dozens of clients and always keep all the branches in sync.
回答10:
To simultaneously push to multiple branches, simply install & configure SourceTree and select "Push" and the branches you wish to deploy to.