Управление многими репозиториями git
Настроить проект легко в git, поэтому у меня может быть отдельный репозиторий даже для небольших скриптов. Теперь проблема в том, как ими управлять.
Я работаю в нескольких местах с этими хранилищами. Когда я внес изменения в некоторый репозиторий, я хочу иметь возможность обновлять репозитории в других местах.
Итак, у меня есть каталог со многими хранилищами.
- Как я могу получить их все?
- Как я могу проверить, есть ли у кого-нибудь незафиксированные изменения?
- Как я могу проверить, есть ли изменения в слиянии?
И было бы неплохо сделать это с помощью одной команды.
Вывод должен быть достаточно тихим, чтобы заметить, что нужно делать.
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;)
Я написал инструмент командной строки под названием 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
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 может помочь вам написать сценарий для ваших сценариев.
Как я могу получить их все?
repo sync
в решении гуглаКак я могу проверить, есть ли у кого-либо из них незафиксированные изменения? Вы можете легко написать свою логику, используя функцию lib
Как я могу проверить, есть ли у кого-либо из них изменения для слияния?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
Я только что создал инструмент, который делает то, что вы хотите!
- Как я могу получить их все?
gmaster fetch
- Как я могу проверить, есть ли у кого-нибудь незафиксированные изменения?
gmaster status
- Как я могу проверить, есть ли изменения в слиянии?
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), чтобы создать пакетный сценарий / сценарий оболочки и выполнить его за один раз. С помощью этого простого глупого решения я знаю, что делаю и чего могу ожидать от выполнения этих команд. Никаких догадок, никакого обучения, никакой настройки. Другая причина в том, что каждый раз я хочу выполнять команды в разных наборах репозиториев, которые находятся в общем родительском каталоге.
Чтобы получить код из всех репозиториев, выполните следующие шаги:
- создать новый файл с расширением .bat
- поместите этот файл в ту же иерархию, где у вас есть все папки репозитория
- отредактируйте .bat файл и добавьте нижеупомянутый скрипт
FOR /D %%G in (%cd%\*) Do cd %%G & call git branch & call git pull & cd ..
echo All code pulled successfully!!
pause
- сохраните файл и дважды щелкните, чтобы начать извлечение кода
https://github.com/wwjamieson3/envisionTools имеет скрипт bash под названием gitstat, который делает это и многое другое. Это GNU и Mac совместимы. Он может выполнять выборки с пульта, если его попросят. Он показывает неотслеживаемые, измененные, добавленные, удаленные и помеченные файлы. Он отличается от удаленных, показывая незакрытые коммиты на удаленных и не помещенные локальные коммиты. Он также может отображать результаты с цветовой кодировкой в кратком или подробном режиме и даже в формате HTML. Он использует locate вместо find, потому что он бесконечно быстрее и даже предложит обновить базу данных locate, если она устарела.