Commit to multiple branches at the same time

Git

Git Problem Overview


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.

Git Solutions


Solution 1 - Git

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!

Solution 2 - Git

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

Solution 3 - Git

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.

Solution 4 - Git

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

Solution 5 - Git

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.

Solution 6 - Git

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"

Solution 7 - Git

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.

Solution 8 - Git

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()

Solution 9 - Git

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 = [email protected]: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.

Solution 10 - Git

To simultaneously push to multiple branches, simply install & configure SourceTree and select "Push" and the branches you wish to deploy to. enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTheOneTeamView Question on Stackoverflow
Solution 1 - GitspoutnikView Answer on Stackoverflow
Solution 2 - GitTheOneTeamView Answer on Stackoverflow
Solution 3 - GitPhilip OakleyView Answer on Stackoverflow
Solution 4 - GitrangaloView Answer on Stackoverflow
Solution 5 - GitharaldView Answer on Stackoverflow
Solution 6 - GitPraveenMakView Answer on Stackoverflow
Solution 7 - GitpandaView Answer on Stackoverflow
Solution 8 - GitrkiyanchukView Answer on Stackoverflow
Solution 9 - GitMartin GerhardyView Answer on Stackoverflow
Solution 10 - GitNative_Mobile_Arch_DevView Answer on Stackoverflow