Управление множеством репозиториев git


87

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

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

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

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

И было бы неплохо иметь возможность делать это одной командой.

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


Тот же вопрос ответил на hg mercurial.
Серж Строобандт

Я использую функцию выбора нескольких курсоров / многострочного редактирования моего редактора кода (код VS), чтобы создать пакетный сценарий / сценарий оболочки и выполнить его за один раз. С помощью этого простого глупого решения я знаю, что делаю и чего могу ожидать от выполнения этих команд. Никаких догадок, никакого обучения, никакой настройки. Другая причина в том, что каждый раз я хочу выполнять команды в разных наборах репозиториев, которые находятся в общем родительском каталоге.
IsmailS

Ответы:


45

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

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

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

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

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

это здорово, но не поддерживает теги git (по состоянию на 2016-08)
Уго Сарагоса,

@CADbloke не упоминает окна на странице установки, но как Perl-скрипт может / должен / мог бы работать с окнами.
scipilot 01

2
@HugoZaragoza, вы всегда можете определить эту команду самостоятельно [ПО УМОЛЧАНИЮ] tag = git tag "$ @"
AlexS

2
alias pa='find . -name .git -print -execdir git pull \;'тогда paдостаточно
DawnSong

19

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

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

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

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


Ваш ответ предполагает, что mu-repo лучше, чем то, что делает mr. Но mu-repo не поддерживает репозитории без git.
Шаунак Сонтакке,

1
Уилл, его цель действительно поддерживать только репозитории git (об этом и спрашивается) - хотя вы также можете mu sh <some command>выполнить некоторую произвольную команду в нескольких репозиториях, вся ее окончательность связана с git, а не с другими системами контроля версий .. Если вам это нужно, то да, используйте другой инструмент.
Фабио Задрозный

14

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


Похоже, с тех пор разработка немного
оживилась

8

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

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


2
git-submodule было бы хорошо, если бы я хотел сохранить репозитории в одном и том же состоянии, но это не так. Набор репозиториев не везде одинаков. Могут быть незафиксированные изменения. Могут быть изменения, которые я пока не хочу объединять.
iny 03

Я не знал о git-submodule. Спасибо, что упомянули об этом.
sykora

Документация для репо довольно минимальна и похоже, что она предназначена для разных рабочих процессов, которые я хочу использовать.
iny

6

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

После обнаружения репозитории «отслеживаются». Это просто покажет их в списке локальных репозиториев, включая плотную информацию о статусе, вдохновленную posh-git . Он содержит текущую ветку и другие вещи, такие как редактирование файлов и количество входящих или исходящих коммитов.

RepoZ UI

Это помогает отслеживать ваши локальные репозитории и незавершенную работу для фиксации или отправки. Кроме того, вы можете использовать список репозиториев в качестве навигации для перехода от одного репозитория к другому.

RepoZ Navigation

"Как я могу получить их все?"

Версия для Windows предлагает контекстное меню для извлечения или извлечения репозитория. С помощью множественного выбора вы можете запускать действия в нескольких репозиториях одновременно.

Однако вы можете найти еще одну очень полезную функцию:

RepoZ Auto-Fetch

С помощью Auto fetch вы можете указать RepoZ периодически извлекать пульты всех ваших репозиториев git в фоновом режиме. Конечно, эти выборки не будут конфликтовать с вашими локальными коммитами. Попыток локального слияния вроде с git pull.


Да уж, плохо и не заслужено. Открыт для PR в любое время. Маякни мне.
Waescher

5

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

Обычно это используется для проектов, где вам нужно собрать несколько репозиториев вместе и держать их в одной ветке или теге одновременно или что-то еще. Для моего каталога (голых) репозиториев у меня есть небольшой make-файл, который позволяет мне запускать произвольные команды 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

5

Я создал псевдоним и функцию для запуска любой команды 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 "$@" \;
}

Надеюсь, поможет :)


1
тонкий и полезный!
Кевин Чоу

Фантастический! Простой один лайнер положить в .bash_aliases: alias rgit='function _rgit(){ find . -type d -name .git -printf "\n%p\n" -execdir git "$@" \;; }; _rgit'. Источник, затем, например, вызов rgit status.
ford04

4

Для этого можно использовать 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

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

git status-all --fetch

git status все


1
Очень красивый подход. В отличие от большинства инструментов, получивших более высокую оценку, нет необходимости сначала регистрировать репозитории, вместо этого он просто проверяет все подкаталоги.
luator

find . -name .git -print -execdir git status \;в порядке
DawnSong

3

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

#!/bin/sh
if [ ! "$1" = "" ] ; 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 $1"
            cd $GITREPO/$dir ; git $@
            echo
         fi

      done
   else

      echo "Git repositories not found."

   fi
fi

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

Этот сценарий основан на этом сценарии .


find . -name .git -print -execdir git pull \;делает то, что вы думаете.
DawnSong

3

Я написал инструмент командной строки под названием gita для управления несколькими репозиториями. Он показывает статус зарегистрированных репозиториев рядом, например

введите описание изображения здесь

Он также может делегировать команды / псевдонимы git из любого рабочего каталога.

Теперь, чтобы ответить на ваши вопросы с помощью этого инструмента:

Как я могу получить их все?

gita fetch

Как я могу проверить, есть ли в каких-либо из них незафиксированные изменения?

Команда gita lsпоказывает 3 возможных символа рядом с названием ветки, что указывает на

  • +: поэтапные изменения
  • *: неустановленные изменения
  • _: неотслеживаемые файлы / папки

Как я могу проверить, есть ли какие-либо изменения для объединения?

Названия веток раскрашены 5 способами

  • белый: в локальном филиале нет удаленного филиала
  • зеленый: локальная ветка такая же, как удаленная ветка
  • красный: локальная ветка отошла от удаленной ветки
  • фиолетовый: локальная ветка опережает удаленную ветку (хорошо для push)
  • желтый: локальная ветка находится за удаленной веткой (подходит для слияния)

Чтобы установить его, просто запустите

pip3 install -U gita

2

Если кто-то все еще просматривает эту ветку, пожалуйста, проверьте мой сценарий оболочки под названием 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

Я устанавливаю псевдоним в моем ~ / .bash_profile, поэтому alias gitme='sh /path/to/gitme.sh'


1

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

Из документов:

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


1

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

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

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


1

Я написал эту простую функцию bash в свой .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.

можно также запустить их все параллельно, используя: all './gradlew clean test &'
ChaudPain

0

Отказ от ответственности: я работаю над этим инструментом на www.repoflow.com

Как я могу получить их все?
Как я могу проверить, есть ли какие-либо изменения для объединения?

  • Вы можете получить все задействованные репозитории (или нажать / вытащить / зафиксировать их), после получения пользовательский интерфейс будет обновлен с новым состоянием репозитория, если репозиторий расходится, вы можете увидеть тип конфликтов и начать их объединение.

введите описание изображения здесь

Как я могу проверить, есть ли в каких-либо из них незафиксированные изменения?

  • В пользовательском интерфейсе вы можете видеть состояние файлов для каждого репозитория (вы можете добавлять / удалять их по отдельности или сразу).

введите описание изображения здесь

Я работаю над этим, но это также решает вопросы OP и помогает управлять несколькими репозиториями в целом. Вы можете использовать пользовательский интерфейс или базовый GraphQL API для создания собственных скриптов, рассмотрите это как еще один вариант.


0

Есть удобный инструмент для получения всех нескольких репозиториев. git-pull-all- это инструмент командной строки для асинхронного выполнения в нескольких репозиториях git.

Установка

npm install -g git-pull-all

Применение

Предположим, у вас есть эти файлы и каталоги:

~/Projects/
  cool-examples/
    .git/
  funny-movies/
  my-todos.txt
  super-express/
    .git/

Когда вы запускаете git-pull-allкоманду в ~/Projectsкаталоге, она должна найти дочерние репозитории git (в приведенном выше случае - cool-examples и super-express ), а затем выполнить git pullдля каждого из них.

$ cd ~/Projects
$ git-pull-all
funny-movies/
Not a git repository
cool-examples/
Already up-to-date.
super-express/
Already up-to-date.
Done!
git-pull-all ~/Projects

Ссылка на GitHub: https://github.com/tatsuyaoiw/git-pull-all


0

Я использую код Visual Studio. У нас есть около 20 библиотек в нашей кодовой базе, которые являются отдельными репозиториями Git, а вкладка управления версиями в Visual Studio Code довольно хороша для того, чтобы увидеть «с первого взгляда», насколько далеко отстают или опережают локальные репозитории. Есть также настройки, которые нужно периодически получать, чтобы поддерживать эту информацию в актуальном состоянии, а также кнопка обновления.

Это не так удобно, как сценарий, но когда дело касается контроля версий, мне нравится вносить изменения. Требуется очень хорошо написанный сценарий, чтобы не перезаписывать изменения и т. Д. Используя подход VS Code, вы быстро получаете большой объем информации, которую вы можете предпринять самостоятельно.

Вот скриншот того, как это выглядит:

Окно управления версиями в VS Code


0

Я нашел отличное решение для извлечения из текущей ветки из всех подкаталогов, в которых есть папка .git, даже если в каждом репо есть другая ветка. Эта команда однострочная, достаточно гибкая, чтобы изменять ее для различных команд git, и может иметь псевдоним.

Просто скопируйте и вставьте следующее:

find . -type d -maxdepth 2 -name .git -exec sh -c 'cd $0 && cd .. && git pull origin $(git rev-parse --abbrev-ref HEAD)' {} \;

Разбивая это:

find . -type d -maxdepth 2 -name .git 

Найдите все каталоги (-type d) в текущем каталоге (find.), Которые имеют имя ".git" (-name .git), просматривая максимум два каталога в глубину (2, а не 1, потому что мы ищем git в папке репозитория git).

-exec sh -c 

Выполните следующую команду оболочки (exec sh -c)

'cd $0 && cd .. && git pull origin $(git rev-parse --abbrev-ref HEAD)'

Измените каталог на первый аргумент (cd $ 0), затем смените каталог на один уровень выше, чтобы оставить папку .git (cd ..), затем выполните git pull origin, указав ветку, запустив git rev-parse ... для текущей ветки HEAD фиксация.

{} \;

"{}" - это относительный путь результата, который мы получаем от начальной команды поиска . The; используется для завершения команды.

Проверено на MacOS 10.14.6 на zsh. Как есть, работает только тогда, когда удаленная и локальная ветки названы одинаково, AFAIK.

Вы можете изменить это, чтобы получить статус. Я надеюсь, что вы сможете добавить аргументы, чтобы сделать это более гибким, но я еще не пробовал.


0

Я использую функцию выбора нескольких курсоров / многострочного редактирования моего редактора кода (код VS), чтобы создать пакетный сценарий / сценарий оболочки и выполнить его за один раз. С помощью этого простого глупого решения я знаю, что делаю и чего могу ожидать от выполнения этих команд. Никаких догадок, никакого обучения, никакой настройки. Другая причина заключается в том, что каждый раз я хочу выполнять команды в разных наборах репозиториев, которые находятся в общем родительском каталоге.


-1

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


2
Спасибо, что разместили свой ответ! Не забудьте внимательно прочитать FAQ по саморекламе . Также обратите внимание, что необходимо публиковать отказ от ответственности каждый раз, когда вы ссылаетесь на свой собственный сайт / продукт.
Эндрю Барбер

3
К сожалению, ссылка на github wwjamieson3 / envisionTools не работает.
Бренда Дж. Батлер,

@williamJamieson is envisionTools - это частный репозиторий GitHub?
eebbesen

-5

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


Я знаю, что уже поздно, но не могли бы вы опубликовать сценарий?
l0b0

Нет никакого «сценария». Я использую сценарий, который написал для своих нужд, но он не является универсальным.
iny

"git diff" на самом деле сложно, если вы хотите получить один файл diff, который можно восстановить и повторно применить с помощью одной команды patch.
proski

4
Буквально любой из ответов должен быть принятым ответом, кроме этого.
Kennet Celeste
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.