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

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

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

Итак, у меня есть каталог со многими хранилищами.

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

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

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

26 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

gita fetch

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

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

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

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

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

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

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

pip3 install -U gita

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

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

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

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

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

Тем не менее, вы можете найти другую функцию очень полезной:

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

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

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

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

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

Вы можете использовать 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 all

gitslave - это инструмент, который может запускать одну и ту же команду во многих репозиториях, создавая отношение суперпроект / подпроект между супер и субпроектами. Это (по умолчанию) обеспечивает суммирование вывода, так что вы можете сосредоточиться на репозиториях, которые предоставляют уникальный вывод (полезно для состояния git, не очень полезно для 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

Я использую этот скрипт, чтобы легко выполнять команды 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 по своему вкусу.

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

Для этого можно использовать every который может запускать команды cli в нескольких каталогах по этому шаблону every <command>

Установить: npm i -g every-cli

Пример использования: every git branch

      - repo-1
  master
- repo-2
  develop

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

Я написал для этого CLI-инструмент, см . https://manicli.com/. Он также имеет несколько приятных дополнительных функций:

  • Запускать команды во многих репозиториях
  • Декларативная конфигурация
  • Гибкая фильтрация, выберите 1 проект, проекты с тегом или подпутью

Я нашел отличное решение для извлечения из текущей ветки из всех подкаталогов, в которых есть папка.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.

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

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

Расширение на /questions/23891492/upravlenie-mnogimi-repozitoriyami-git/23891507#23891507 (теперь репо доступно на GitHub)

Я предлагаю вам проверить этот инструмент https://github.com/googleapis/github-repo-automation , используемый Google для управления несколькими репозиториями.

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

https://github.com/tj/git-extras может помочь вам написать сценарий для ваших сценариев.

  1. Как я могу получить их все?repo syncв решении гугла

  2. Как я могу проверить, есть ли у кого-либо из них незафиксированные изменения? Вы можете легко написать свою логику, используя функцию lib

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

проверьте команды git extras для идей, см. https://github.com/tj/git-extras/blob/master/Commands.md#git-show-unmerged-branches

Пожалуйста, попробуйте Гиту .

gitas statusфлаги:

        -t, --time           time of last commit shown (default true)
  -f, --format {r|i}   format time: relative|iso (default r)
  -b, --branch         branch shown
  -q, --query          query fetch needed (implies -br)
  -r, --remote         remote shown
  -l, --url            url shown
  -d, --dirty          dirty shown (default true)
  -u, --untracked      untracked shown
  -s, --stash          stash shown
  -o, --order {t|n}    order: time|name (default t)
  -e, --emit {t|j|m}   emit format: table|json|markdown (default t)
  -h, --help           help for status

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

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

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

Есть удобный инструмент для получения всех нескольких репозиториев.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

Disclaimer: I am working on this tool at http://www.repoflow.com/

How can I fetch all of them?
How can I check whether any of them have changes to merge?

  • You can fetch all the involved repositories (or push/pull/commit them), after the fetch the UI will be updated with the new repository state, if the repository is diverged you can see the kind of conflicts and begin merge them.

How can I check whether any of them have uncommitted changes?

  • On the UI you can see the state of the files for each repository (You can add/remove them individually or in bulk).

I am working on this, but this is also solving the OP questions and help manage multiple repositories in general, you can use the UI or the underlying GraphQL API to create your own scripts, please consider it as another option.

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

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

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

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

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

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

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

Чтобы получить код из всех репозиториев, выполните следующие шаги:

  1. создать новый файл с расширением .bat
  2. поместите этот файл в ту же иерархию, где у вас есть все папки репозитория
  3. отредактируйте .bat файл и добавьте нижеупомянутый скрипт
      FOR /D %%G in (%cd%\*) Do cd %%G & call git branch & call git pull & cd ..
echo All code pulled successfully!!
pause
  1. сохраните файл и дважды щелкните, чтобы начать извлечение кода

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

Другие вопросы по тегам