【问题标题】:Commit to multiple branches at the same time同时提交到多个分支
【发布时间】:2011-11-07 17:13:16
【问题描述】:

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

说,我在分支 A 上做了一个新的功能提交。我也可以同时在分支 B、分支 C 和 D 上进行这个提交吗?是否有任何快捷命令?签出一个分支非常麻烦,每次都选择提交,有时,如果在许多分支上都需要提交,那对我来说将是一场噩梦。

有任何简单的 bash 脚本用于此操作吗?

里面有一个similar question。但变基不是我想要的。

【问题讨论】:

标签: git


【解决方案1】:

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

【讨论】:

  • 我不想进行合并,因为我不想让所有分支都相同。 Cherry-pick 是一种选择,但需要时间,需要结帐到每个分支,如果我有超过 5 个分支要做,则需要时间......好吧,你认为做一个脚本可以吗?
  • 编写这个脚本应该相当简单。还要检查@rangalo 的答案。
【解决方案2】:

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

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

http://git-scm.com/docs/githooks

【讨论】:

    【解决方案3】:

    您可能想查看的内容:git stash 您的更改、git commitgit checkout 另一个分支、git stash applygit commit 等。

    请参阅man pages

    【讨论】:

    • 此方案可行,但您需要git stash apply,而不是git stash pop
    • @wjl:感谢您的更正 - 我应该指示 Kit Ho 也阅读手册页 ;-)
    • 只有在你不想将分支合并在一起时才这样做,因为它会产生有保证的冲突,因为两个不同的提交会尝试做同样的改变。在OP的情况下,应该是这种情况。此警告适用于阅读此内容的其他人。
    【解决方案4】:

    由于我的问题没有典型的答案,我编写了一个简单的脚本来自动化这个过程。随意评论此代码。

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

    【讨论】:

    • 那你为什么不接受你的答案作为解决方案呢?
    • for 循环中的命令应该与&& 链接,这样如果一个失败,下一个不会运行。 (例如:摘樱桃时发生冲突)
    【解决方案5】:

    我认为没有办法。也许您需要为它编写一个 bash 脚本或为不同的分支制作不同的 repo。

    【讨论】:

      【解决方案6】:

      cherry-pick 功能将完成这项工作,并且只会应用最后一次提交:

      考虑分支 A、B

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

      希望这会有所帮助!

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          【解决方案8】:

          这可能取决于您将如何推送您的提交。我的意思是你总是有机会使用一个git push 命令进入多个分支。

          执行以下.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 
          

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

          【讨论】:

            【解决方案9】:

            也许这会对某些人有所帮助,

            我使用了上面“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"
            

            【讨论】:

            • 好吧,这吓到我了
            【解决方案10】:

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

            【讨论】:

              猜你喜欢
              • 2011-05-30
              • 2019-12-31
              • 1970-01-01
              • 2017-04-26
              • 2016-07-29
              • 1970-01-01
              • 2015-09-17
              • 2016-03-23
              • 2016-01-04
              相关资源
              最近更新 更多