2011-08-31 15 views
13

Quiero hacer una única confirmación en diferentes ramas al mismo tiempo, ya que, en mi proyecto, tengo diferentes sucursales para diferentes clientes.Git: Comprometerse a varias sucursales al mismo tiempo

Diga, he hecho una nueva función confirmada en la Sucursal A. ¿Puedo hacer esta confirmación también en la Rama B, Rama C y D al mismo tiempo? ¿Hay algún comando de atajo para esto? Esto es muy problemático para pagar una sucursal, y recoger el compromiso cada vez, en algún momento, si la confirmación es necesaria en muchas sucursales, sería una pesadilla para mí.

¿Algún script bash simple para esta operación?

Hay un similar question allí. pero el rebase no es lo que quiero.

+0

posible duplicado de [Commit a múltiples ramas al mismo tiempo con git] (http://stackoverflow.com/questions/4532063/commit-to-multiple-branches-at-the-same-time- with-git) – Johann

+0

Véase también http://stackoverflow.com/a/30186843/6309 – VonC

+0

Si la respuesta de Spoutnik lo ayudó, considere aceptarla con la marca de verificación verde –

Respuesta

0

No, no creo que puedas hacer esto. Su mejor opción sería comprometerse con una de sus sucursales (o una sucursal principal) y luego fusionar el compromiso con los demás uno por uno, o seleccionar cuidadosamente el compromiso en cada una de las otras ramas.

+0

No quiero hacer una fusión ya que no quiero hacer que todas las ramas sean iguales. Cherry-pick es una opción, pero lleva tiempo, necesita realizar el pago en todas las sucursales, si tengo más de 5 sucursales, necesita tiempo ... bueno, ¿cree que un script puede hacerlo? –

+0

Sería bastante trivial escribir esto. También verifique la respuesta de @ rangalo. – harald

2

Creo que puede escribir un gancho post-commit para combinar o seleccionar con las otras ramas. Pero, por supuesto, no será un compromiso único.

Hook automatizará lo que desea lograr.

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

7

Algo es posible que desee echar un vistazo a: git stash sus cambios, git commit, git checkout otra rama, git stash apply, git commit, etc.

Ver la man pages.

+1

Este esquema funcionará, pero quieres 'git stash apply', no' git stash pop'. – wjl

+0

@wjl: Gracias por la corrección: debería haber ordenado a Kit Ho que también lea las páginas man ;-) –

9

Dado que no hay una respuesta típica para mi pregunta, he escrito una secuencia de comandos simple para automatizar este proceso. Siéntase libre de comentar este código.

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

¿Por qué no acepta su respuesta como solución entonces? – Sampath

0

No creo que haya una manera de hacerlo. Tal vez necesites escribir un script bash para él o crear un repositorio diferente para diferentes ramas.

33

La función de cereza-escoge hará el trabajo y sólo se aplicará de la última confirmación:

Teniendo en cuenta las ramas A, B

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

esperanza que esto ayude!

0

También se puede hacer buen uso de la automatización de algunos de 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() 
0

Se podría depender de cómo se va a distribuir sus confirmaciones. Quiero decir que siempre tienes la posibilidad de insertar en varias sucursales con un solo comando git push.

Realice las siguientes configuraciones .git/config para asegurarse de que la rama master siempre se empujará a la rama foobar, también.

[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 

Pero el problema aquí podría ser que si estas dos ramas divergían, no se puede empujar hacia ellas.Aún puede reorganizar su código para que la detección del cliente se base en la sucursal que está creando. De esta forma, podría mantener docenas de clientes y mantener sincronizadas todas las ramas.

0

Tal vez esto ayudará a algunas personas,

que utiliza el método del "Kit de Ho" s arriba y lo añadió a .gitconfig como 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" 
Cuestiones relacionadas