Управление многими репозиториями git

настройка проекта легко в git, и поэтому я могу иметь отдельный репозиторий даже для небольшого скрипта. Теперь проблема в том, как ими управлять.

Я работаю в нескольких местах с этими репозиториями. Когда я внес изменения в какой-то репозиторий, я хочу иметь возможность обновлять репозитории в других местах.

поэтому у меня есть каталог со многими репозиториями в нем.

  1. как я могу получить все из них?
  2. как я могу проверить, есть ли какой-либо из них есть незафиксированные изменения?
  3. как я могу проверить, есть ли какие-либо из них изменения для слияния?

и было бы неплохо сделать это с помощью одной команды.

выход должен быть достаточно тихим, чтобы действительно заметить, что нужно делать.

14 ответов


Я настоятельно рекомендую инструмент нескольких репозиториев г. Я использовал пользовательский сценарий оболочки, как рекомендовали другие в течение некоторого времени, но использование mr имеет следующие преимущества для меня:

  • это общий: можно использовать сочетание различных систем управления версиями, а не только git (например, Mercurial, SVN и т. д.).
  • это быстро: mr может выполнять несколько заданий параллельно. Я использую несколько репозиториев git/mercurial и синхронизирую их несколько раз в день. Mr чрезвычайно ускоряет этот процесс.
  • легко и быстро управлять список касс. Просто используйте "mr register" вместо изменения списка проектов в вашем пользовательском скрипте.

Что касается вашего вопроса о silent output: уровень детализации можно изменить с помощью переключателя командной строки-q. Я предпочитаю вывод по умолчанию, который, кажется, хорошо объединяет вывод в коротком и ясном резюме.

Я использую следующий псевдоним для команды mr, чтобы убедиться, что mr всегда берет мой список проектов по умолчанию, хранящийся в $HOME, и использует 5 параллельных потоков:

alias mr='mr -d ~/ -j 5 '

должен сказать, что я начал с принятого в настоящее время ответа (просто куча сценариев помощников, которые повторяют репозитории), но в целом, мне не хватало опыта.

Итак, попробовав mr, repo и Git-подмодули, я обнаружил, что каждому не хватает по-разному, поэтому я закончил свой собственный вариант:http://fabioz.github.io/mu-repo который является зрелым инструментом на данный момент-он имеет рабочие процессы, которые позволяют:

  • клонировать несколько repos
  • diff (и редактировать) текущие изменения в нескольких репозиториях
  • предварительный просмотр входящих изменений
  • запуск команд в нескольких репозиториях параллельно
  • создать группы РЕПО
  • выполнить команды, не связанные с git, через несколько репозиториев
  • и т. д. (см. Домашняя страница для получения дополнительной информации).

обратите внимание, что он поддерживает любую ОС, где работает Python;)


gr (git-run) расширяет гфункциональность (только для git). Мне проще организовать несколько репозиториев git, используя его систему тегов. Код gr Не поддерживается, хотя. Если вы используете bash, убедитесь, что вы используете его с -t tag вместо #tag форма.


Вы можете попробовать использовать РЕПО с пользовательским manifest.xml файл, чтобы указать, где находятся ваши репозитории. Есть документация о том, как это сделать.

в качестве альтернативы вы можете использовать git-submodule(1).


gitslave - это инструмент, который может запускать одну и ту же команду над многими репозиториями, создавая связь superproject/subproject между super и subs. Это (по умолчанию) обеспечивает суммирование вывода, поэтому вы можете сосредоточиться на репозиториях, которые предоставляют уникальный вывод (полезно для состояния git, не так полезно для ls-файлов git).

это обычно используется для проектов, где вам нужно собрать несколько репозиториев вместе и сохранить их на одном и том же ветка или бирка в то же время или что-то еще. Для моего каталога (голых) репозиториев у меня просто есть немного makefile, который позволяет мне запускать произвольные команды git, которые, как вы видите, я в первую очередь использую для fsck и gc:

full: fsck-full gc-aggressive
        @:

fsck-full:
        for f in */.; do (cd $$f; echo $$f; git fsck --full || echo $$f FAILED); done

gc-aggressive:
        for f in */.; do (cd $$f; echo $$f; git gc --aggressive || echo $$f FAILED); done

%:
        for f in */.; do (cd $$f; git $@ || echo $$f FAILED); done

Я использую этот скрипт для легкого выполнения команд git во всех моих репозиториях.

#!/bin/sh
if [ ! "" = "" ] ; then

   if [ "$GITREPO" = "" -a -d "$HOME/cm/src" ] ; then
      GITREPO="$HOME/cm/src"
   fi

   if [ "$GITREPO" != "" ] ; then

      echo "Git repositories found in $GITREPO"
      echo "-=-=-=-=-=-=-=-=-=-=-=-=-=-"

      DIRS="`/bin/ls -1 $GITREPO`"

      for dir in $DIRS ; do

         if [ -d $GITREPO/$dir/.git ] ; then
            echo "$dir -> git "
            cd $GITREPO/$dir ; git $@
            echo
         fi

      done
   else

      echo "Git repositories not found."

   fi
fi

по умолчанию скрипт будет искать репозитории git в ~/cm / src, но вы можете переопределить это, установив переменную среды GITREPO по своему вкусу.

этот скрипт основан на этот скрипт.


можно использовать git-status-all драгоценный камень для этого:https://github.com/reednj/git-status-all

# install the gem    
gem install git-status-all

# use the status-all subcommand to scan the directory
git status-all

существует также опция fetch, которая будет получать из origin для всех репозиториев перед отображением статуса:

git status-all --fetch

git status all


Я только что создал инструмент, который делает то, что вы хотите!

  1. как я могу принести все из них? gmaster fetch
  2. как я могу проверить, есть ли какие-либо из них незафиксированные изменения? gmaster status
  3. как я могу проверить, есть ли какие-либо из них изменения для слияния? gmaster status

он называется gitmaster:https://github.com/francoiscabrol/gitmaster


Я написал эту простую функцию bash в my .bash_profile, чтобы иметь возможность запускать git, maven, gradle или любую другую команду bash только во всех репозиториях git:

# usefull function to work with multiple git repositories
all() {
    failed=0
    printf '>>> START RUNNING: "%s" >>>' "$*"
    for d in */; do
        pushd "$d" > /dev/null
        if [ -d ".git" ]
        then
            printf '\n--------------------------------------------\n\n'
            pwd
            eval $@
            if [ $? -ne 0 ]
            then
                failed=1
                break;
            fi
        fi
        popd > /dev/null
    done
    if [ $failed -eq 0 ]
    then
        printf '\n--------------------------------------------\n'
        printf '<<< RAN "%s" WITH SUCCESS!!! <<<' "$*"
    else
        printf '\n<<< FAILED!!! <<<'
    fi
}

Это можно использовать таким образом

all git st
all git pull
all ./gradlew clean test
etc.

вы должны проверить rgit на CPAN, который рекурсивно выполняет команды git на всех репозиториях в дереве каталогов.

документы:

эта утилита рекурсивно ищет в корневой каталог (который может быть текущий рабочий каталог или-если это был установлен-каталог, заданный переменная среды GIT_DIR) для все репозитории git, отсортируйте этот список по пути репозитория, chdir в каждый из них, и исполняет указанный команду git.


Если кто-то все еще смотрит на эту тему, пожалуйста, проверьте мой сценарий оболочки под названием gitme

вам нужно будет вручную ввести локальные репозитории git, но я использую этот инструмент каждый день для совместной работы нескольких проектов git на нескольких компьютерах.

вы можете запустить git clone https://github.com/robbenz/gitme.git

также скрипт размещен ниже

#!/bin/bash -e

REPOS=( 
/Users/you/gitrepo1
/Users/you/gitrepo2
/Users/you/gitrepo3
/Users/you/gitrepo4
)

MOVE="Moving to next REPO... \n" 

tput setaf 2;echo "What ya wanna do? You can say push, pull, commit, ftp push, or status"; tput sgr0

read input

if [ $input =  "commit" ]
then
    tput setaf 2;echo "Do you want a unique commit message? [y/n]";tput sgr0
    read ans
    if [ $ans = "y" ]
    then 
        for i in "${REPOS[@]}"
        do
            cd "$i"
            tput setaf 6;pwd;tput sgr0 
            git add . -A
            read -p "Commit description: " desc  
            git commit -m "$desc"
            tput setaf 2;echo  $MOVE;tput sgr0 
            sleep 1
        done 
    else 
        for i in "${REPOS[@]}"
        do
            cd "$i"
            tput setaf 6;pwd;tput sgr0 
            git add . -A
            git commit -m "autocommit backup point"
            tput setaf 2;echo  $MOVE;tput sgr0 
            sleep 1
        done
    fi 
elif [ $input = "push" ] || [ $input = "pull" ] || [ $input = "ftp push" ] || [ $input = "status" ]
    then
        for i in "${REPOS[@]}"
do
    cd "$i"
    tput setaf 6;pwd;tput sgr0 
    git $input 
    tput setaf 2;echo  $MOVE;tput sgr0 
    sleep 1
    done 
else tput setaf 1;echo "You have zero friends";tput sgr0 
fi

создать псевдоним в моем ~/.файл так alias gitme='sh /path/to/gitme.sh'


Я сделал псевдоним и функцию для запуска любой команды git во всех репозиториях, доступных в каталоге (рекурсивно). Вы можете найти его здесь: https://github.com/jaguililla/dotfiles/git

этот код:

#!/bin/sh
# To use it: source git_aliases

# Example: rgita remote \;
alias rgita='find . -type d -name .git -execdir git'

# Example: rgit remote -vv
rgit() {
  rgita "$@" \;
}

надеюсь, что это помогает :)


https://github.com/wwjamieson3/envisionTools есть bash-скрипт называется gitstat, что это и многое другое. Он совместим с GNU и mac. Он может выполнять выборки из пультов дистанционного управления, если его спросят. Он показывает неотслеженные, измененные, добавленные, удаленные и поэтапные файлы. Его разногласия с пультов показывая неслиянно совершает на пульты и unpushed локальные коммиты. Он также может отображать цветовые результаты в сводном или подробном режиме и даже HTML. Он использует locate вместо find потому что это бесконечно быстрее и даже предложит обновить базу данных locate, если она становится слишком старой.


похоже, написать сценарий, чтобы сделать это довольно легко. По сути, он должен перебирать репозитории, а затем использовать команды, такие как Git ls-files, git diff и git log.