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

87

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

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

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

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

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

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

iny
источник
Тот же вопрос ответил на 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) .

Spoike
источник
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.

Waescher
источник
Да уж, плохо и не заслужено. Открыт для 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 "$@" \;
}

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

Jaguililla
источник
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

Francoiscabrol
источник
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.
ChaudPain
источник
можно также запустить их все параллельно, используя: 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

Ty Deuty
источник
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), чтобы создать пакетный сценарий / сценарий оболочки и выполнить его за один раз. С помощью этого простого глупого решения я знаю, что делаю и чего могу ожидать от выполнения этих команд. Никаких догадок, никакого обучения, никакой настройки. Другая причина заключается в том, что каждый раз я хочу выполнять команды в разных наборах репозиториев, которые находятся в общем родительском каталоге.

IsmailS
источник
-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.

iny
источник
Я знаю, что уже поздно, но не могли бы вы опубликовать сценарий?
l0b0
Нет никакого «сценария». Я использую сценарий, который написал для своих нужд, но он не является универсальным.
iny
"git diff" на самом деле сложно, если вы хотите получить один файл diff, который можно восстановить и повторно применить с помощью одной команды patch.
proski
4
Буквально любой из ответов должен быть принятым ответом, кроме этого.
Kennet Celeste