Git 同时提交到多个分支

Git 同时提交到多个分支,git,Git,我想同时在不同的分支上进行一次提交,因为在我的项目中,我为不同的客户机提供了不同的分支 比如说,我在分支a上做了一个新的功能提交。我能同时在分支B、分支C和分支D上做这个提交吗?这有什么捷径吗?签出一个分支非常麻烦,Cherry每次都选择提交,有时,如果在许多分支上都需要提交,这对我来说将是一场噩梦 这个操作有简单的bash脚本吗 里面有一个盒子。但重新定基不是我想要的。不,我认为你做不到。您最好的选择是提交到您的一个分支(或主分支),然后将提交一个接一个地合并到其他分支中,或者将提交挑选到其他

我想同时在不同的分支上进行一次提交,因为在我的项目中,我为不同的客户机提供了不同的分支

比如说,我在分支a上做了一个新的功能提交。我能同时在分支B、分支C和分支D上做这个提交吗?这有什么捷径吗?签出一个分支非常麻烦,Cherry每次都选择提交,有时,如果在许多分支上都需要提交,这对我来说将是一场噩梦

这个操作有简单的bash脚本吗


里面有一个盒子。但重新定基不是我想要的。

不,我认为你做不到。您最好的选择是提交到您的一个分支(或主分支),然后将提交一个接一个地合并到其他分支中,或者将提交挑选到其他每个分支中。

我认为您可以编写一个提交后钩子来合并或挑选其他分支。但它当然不会是一个单一的承诺

Hook将自动实现您想要实现的目标


您可能想看看的东西:
git stash
您的更改,
git提交
git签出
另一个分支,
git stash apply
git提交
,等等


请参阅。

因为我的问题没有典型的答案,所以我编写了一个简单的脚本来自动化这个过程。请随意评论这段代码

#!/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

我认为没有办法做到这一点。也许您需要为它编写bash脚本,或者为不同的分支创建不同的repo。

cherry pick功能将完成此任务,并且只应用最后一次提交:

考虑分支机构A、B

git checkout A
git commit -m "Fixed the bug x"
git checkout B
git cherry-pick A

希望这有帮助

您还可以使用一些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()

这可能取决于您将如何推动提交。我的意思是,您总是有机会使用一个
gitpush
命令推送到多个分支

执行以下
.git/config
设置,以确保
master
分支也始终被推送到
foobar
分支

[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 

但这里的问题可能是,如果这两个分支发散,你就不能推动它们。您仍然可以根据正在构建的分支重新组织您的代码。这样,您可以维护几十个客户端,并始终保持所有分支的同步。

也许这会帮助一些人

我使用了上面的“Kit Ho”方法,并将其作为别名添加到.gitconfig中

; 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"
;commitall提交到当前分支以及分支数组变量中提到的所有分支,如下所示。
commitall=“!f(){\
分行=(\
分支机构1\
分支机构2\
);  \
用法()\
{ \
echo \“用法:git commitall-m'JIRA:BRANCHNAME:'\”\
出口1\
}; \
OPTIND=1\
DFNs=\“\”\
而getopts \“h:m:\”opt\
做\
案例\“$opt\”在\
h)\
用法\
;; \
m) 导出注释=$OPTARG\
;; \
以撒\
完成\
ORIGINALBRANCH=`git符号参考头| cut-d/-f3-`\
echo \“当前分支为$ORIGINALBRANCH\”\
echo$Comment | grep“^JIRA:$ORIGINALBRANCH:\”>/dev/null 2>&1\
如果[$?-ne 0];则\
用法\
fi\
LOGMSG=`git log-1--pretty=%B--grep=\“JIRA:$ORIGINALBRANCH:\”\
MSG='commit first time in this branch is success'\
如果[\“$LOGMSG\”==\“\”],则\
git提交-m\“$Comment\”\
否则\
git commit-a--amend-C头\
MSG='commit with amend successed'\
fi\
如果[$?-ne 0];则\
echo \“git提交失败!\”\
出口1\
否则\
回声\“$MSG\”\
fi\
CHERRYCOMMIT=`git log-n1 | head-n1 | cut-c8-`\
如果[\“$CHERRYCOMMIT\”==\“\”],则\
echo\“'git log-n1 | head-n1 | cut-c8-'no commit for this branch\”\
出口1\
fi\
echo \“找到此提交->当前分支的$CHERRYCOMMIT\”\
stashes=`git stash list | grep\'WIP on$ORIGINALBRANCH\'`\
对于\“${branchs[@]}”中的分支,请执行以下操作\
如果[\“$stashes\”],则\
吉特储藏\
fi\
git结帐$BRANCH\
如果[$?-ne 0];则\
echo \“git签出$BRANCH失败!\”\
出口1\
fi\
git cherry pick$CHERRYCOMMIT\
git checkout$ORIGINALBRANCH\
如果[\“$stashes\”],则\
吉特隐藏流行音乐\
fi\
完成\
}; \
f“

要同时推送到多个分支,只需安装和配置并选择“推送”和要部署到的分支。

我不想合并,因为我不想使所有分支都相同。Cherry pick是一个选择,但它需要时间,需要签出到每个分支,如果我有5个以上的分支要做,它需要时间…嗯,你认为制作一个脚本可以做到吗?编写这个脚本应该是相当简单的。还请检查@rangalo的答案。此方案会起作用,但您需要的是
git stash apply
,而不是
git stash pop
@wjl:谢谢您的更正-我应该让Kit Ho也阅读手册页;-)仅当您不想将分支合并在一起时才执行此操作,因为这将创建保证冲突,因为两个不同的提交将尝试执行相同的更改。在OP的情况下,应该是这样的。此警告供阅读此警告的其他人使用。您为什么不接受您的答案作为解决方案呢?for循环中的命令应与
&&
链接,以便在一个命令失败时,下一个命令不会运行。(例如:采摘樱桃时发生冲突)我认为没有办法做到这一点。也许你需要为它写一个BASH脚本或者为不同的分支做一个不同的重复。如果Spoutnik的回答帮助你,也可以考虑用绿色支票来接受它。