Zarządzanie wieloma repozytoriami git

85

Konfiguracja projektu jest łatwa w git, więc mogę mieć oddzielne repozytorium nawet dla małych skryptów. Teraz problem polega na tym, jak nimi zarządzać.

Pracuję w wielu miejscach z tymi repozytoriami. Kiedy dokonałem zmian w jakimś repozytorium, chcę mieć możliwość aktualizowania repozytoriów w innych miejscach.

Mam więc katalog z wieloma repozytoriami.

  1. Jak mogę je wszystkie pobrać?
  2. Jak mogę sprawdzić, czy któryś z nich ma niezatwierdzone zmiany?
  3. Jak mogę sprawdzić, czy któryś z nich ma zmiany do scalenia?

Byłoby miło móc to zrobić jednym poleceniem.

Wyjście musi być na tyle ciche, aby faktycznie było widoczne, co należy zrobić.

iny
źródło
To samo pytanie odpowiedział na hg mercurial.
Serge Stroobandt

Odpowiedzi:

44

Bardzo polecam narzędzie wielu repozytoriów mr . Używałem przez jakiś czas niestandardowego skryptu powłoki, zgodnie z zaleceniami innych, ale korzystanie z mr ma dla mnie następujące zalety:

  • Jest ogólny: można zastosować połączenie różnych systemów kontroli wersji, nie tylko git (np. Mercurial, SVN itp.).
  • Jest szybki: mr może wykonywać wiele zadań równolegle. Używam wielu repozytoriów git / mercurial i synchronizuję je kilka razy dziennie. Pan ogromnie przyspiesza ten proces.
  • Zarządzanie listą pobrań repozytorium jest łatwe i szybkie. Po prostu użyj „mr register” zamiast modyfikować listę projektów w swoim niestandardowym skrypcie.

Odnośnie twojego pytania o ciche wyjście: Poziom szczegółowości można zmienić za pomocą przełącznika wiersza poleceń -q. Wolę domyślne wyjście, które wydaje się ładnie ujednolicać dane wyjściowe w krótkim i jasnym podsumowaniu.

Używam następującego aliasu dla polecenia mr, aby upewnić się, że mr zawsze wybiera moją domyślną listę projektów przechowywaną w $ HOME i używa 5 równoległych wątków:

alias mr='mr -d ~/ -j 5 '
Sandro Giessl
źródło
5
Czy obsługuje system Windows?
Fitzchak Yitzchaki
jest świetny, ale nie obsługuje tagowania git (stan na 2016-08)
Hugo Zaragoza
@CADbloke nie wspomina o oknach na stronie instalacji, ale jako skrypt Perla może / powinien / mógłby działać w systemie Windows.
scipilot
2
@HugoZaragoza, zawsze możesz samodzielnie zdefiniować to polecenie [DEFAULT] tag = tag git "$ @"
AlexS
2
alias pa='find . -name .git -print -execdir git pull \;'wtedy pawystarczy
DawnSong
19

Muszę powiedzieć, że zacząłem od aktualnie zaakceptowanej odpowiedzi (tylko kilka skryptów pomocniczych, które iterują po repozytoriach), ale w sumie brakowało mi tego doświadczenia.

Tak więc, po wypróbowaniu mr, repo i git-submodules, okazało się, że w każdym z nich brakowało w inny sposób, więc w końcu zrobiłem swój własny wariant: http://fabioz.github.io/mu-repo, który jest dojrzałym narzędziem w ten punkt - ma przepływy pracy, które pozwalają:

  • klonuj wiele repozytoriów
  • diff (i edytuj) bieżące zmiany w wielu repozytoriach
  • podgląd nadchodzących zmian
  • uruchamiaj polecenia w wielu repozytoriach równolegle
  • tworzyć grupy repozytoriów
  • uruchamiaj polecenia niezwiązane z git w wielu repozytoriach
  • itp. ( więcej informacji na stronie głównej ).

Zauważ, że obsługuje każdy system operacyjny, na którym działa Python;)

Fabio Zadrozny
źródło
Twoja odpowiedź sugeruje, że mu-repo jest lepsze niż to, co robi pan. Ale mu-repo nie obsługuje repozytoriów innych niż git.
Shaunak Sontakke
1
Whell, jego celem jest naprawdę obsługa tylko repozytoriów git (o to właśnie zadawano pytanie) - chociaż możesz mu sh <some command>wykonać dowolne polecenie również w wielu repozytoriach, cała jego ostateczność dotyczy git, a nie innych systemów kontroli wersji. .Jeśli tego potrzebujesz, tak, użyj innego narzędzia.
Fabio Zadrozny
14

gr (git-run) rozszerzafunkcjonalność mr (tylko dlagit). Uważam, że łatwiej jest zorganizować wiele repozytoriów git za pomocą jego systemu tagów. Kod dlagrnie jest jednak dobrze utrzymany. Jeśli używasz basha, upewnij się, że używasz go zformą-t tagzamiast#tag.

Zapamiętywanie
źródło
Wygląda na to, że od tamtego czasu rozwój nieco się poprawił
Dave Forgac
8

Możesz spróbować użyć repozytorium z niestandardowym manifest.xmlplikiem, aby określić, gdzie są twoje repozytoria. Istnieje dokumentacja jak to zrobić.

Alternatywnie możesz użyć git-submodule(1) .

Spoike
źródło
2
git-submodule byłby dobry, gdybym chciał zachować repozytoria w dokładnie tym samym stanie, ale tak nie jest. Zestaw repozytoriów nie jest taki sam w każdym miejscu. Mogą wystąpić niezatwierdzone zmiany. Mogą wystąpić zmiany, których jeszcze nie chcę łączyć.
iny
Nie wiedziałem o git-submodule. Dzięki, że o tym wspomniałeś.
sykora
Dokumentacja repozytorium jest dość minimalna i wygląda na to, że jest przeznaczona dla innego rodzaju przepływu pracy, którego chcę używać.
iny
6

Napisałem narzędzie o nazwie „ RepoZ ”, które automatycznie wykrywa repozytoria git, gdy tylko je sklonujesz lub zmieniasz cokolwiek w nich, na przykład przełączanie gałęzi.

Po znalezieniu repozytoria są „śledzone”. To po prostu pokaże je na liście lokalnych repozytoriów, zawierającej obszerne informacje o statusie inspirowane posh-git . Zawiera bieżącą gałąź i inne rzeczy, takie jak edycje plików i liczbę zatwierdzeń przychodzących lub wychodzących.

RepoZ UI

Pomaga to śledzić lokalne repozytoria i niedokończoną pracę do zatwierdzenia lub wypchnięcia. Ponadto możesz użyć listy repozytoriów jako nawigacji do przełączania się z jednego repozytorium do drugiego.

RepoZ Navigation

„Jak mogę je wszystkie pobrać?”

Wersja dla systemu Windows oferuje menu kontekstowe do pobierania lub pobierania repozytorium. Dzięki wielokrotnemu wyborowi możesz uruchamiać akcje na wielu repozytoriach jednocześnie.

Może się jednak okazać, że bardzo przydatna jest inna funkcja:

Automatyczne pobieranie RepoZ

Dzięki funkcji automatycznego pobierania możesz powiedzieć RepoZ, aby okresowo pobierał w tle piloty wszystkich repozytoriów git. Te pobrania nie kolidują oczywiście z lokalnymi zatwierdzeniami. Nie ma lokalnych prób scalania, takich jak z git pull.

Waescher
źródło
Tak, szkoda i nie zasłużyłem. Otwarte dla PR w dowolnym momencie. Pinguj mnie.
Waescher
5

gitslave to narzędzie, które może uruchomić to samo polecenie w wielu repozytoriach, tworząc relację superprojekt / podprojekt między superprojektem a podprojektem. To (domyślnie) zapewnia podsumowanie wyników, dzięki czemu możesz skoncentrować się na repozytoriach, które zapewniają unikalne dane wyjściowe (przydatne dla statusu git, niezbyt przydatne dla git ls-files).

Jest to zwykle używane w projektach, w których musisz złożyć kilka repozytoriów razem i trzymać je w tej samej gałęzi lub tagu w tym samym czasie lub cokolwiek. Dla mojego katalogu (czystych) repozytoriów mam tylko mały plik makefile, który pozwala mi uruchamiać dowolne polecenia git, których, jak widzisz, używam głównie dla fsck i 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
Seth Robertson
źródło
5

Stworzyłem alias i funkcję do uruchamiania dowolnego polecenia git we wszystkich repozytoriach dostępnych w katalogu (rekurencyjnie). Znajdziesz go tutaj: https://github.com/jaguililla/dotfiles/git

To jest kod:

#!/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 "$@" \;
}

Mam nadzieję, że to pomoże :)

jaguililla
źródło
1
smukły i przydatny!
Kevin Chou
Fantatstic! Prosta-liner, aby umieścić w .bash_aliases: alias rgit='function _rgit(){ find . -type d -name .git -printf "\n%p\n" -execdir git "$@" \;; }; _rgit'. Źródło go, a następnie np rgit status. Zadzwoń .
ford 04
4

Możesz do tego użyć git-status-allklejnotu: 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

Istnieje również opcja pobierania, która pobierze ze źródła dla wszystkich repozytoriów przed wyświetleniem statusu:

git status-all --fetch

stan git all

Nathan
źródło
1
Bardzo fajne podejście. W przeciwieństwie do większości narzędzi o wyższej liczbie głosów, nie ma potrzeby rejestrowania repozytoriów, zamiast tego po prostu sprawdza wszystkie podkatalogi.
luator
find . -name .git -print -execdir git status \;jest OK
DawnSong
3

Używam tego skryptu do łatwego wykonywania poleceń git we wszystkich moich repozytoriach.

#!/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

Domyślnie skrypt będzie szukał repozytoriów git w ~ / cm / src, ale możesz to zmienić, ustawiając zmienną środowiskową GITREPO według własnych upodobań.

Ten skrypt jest oparty na tym skrypcie .

Scotts
źródło
find . -name .git -print -execdir git pull \;robi to, co myślisz.
DawnSong
3

Napisałem narzędzie wiersza poleceń o nazwie gita do zarządzania wieloma repozytoriami. Pokazuje na przykład status zarejestrowanych repozytoriów obok siebie

wprowadź opis obrazu tutaj

Może również delegować polecenia / aliasy git z dowolnego katalogu roboczego.

Teraz, aby odpowiedzieć na pytania za pomocą tego narzędzia:

Jak mogę je wszystkie pobrać?

gita fetch

Jak mogę sprawdzić, czy któryś z nich ma niezatwierdzone zmiany?

W gita lspodaje komunikat 3 możliwych znaków obok nazwy gałęzi, co wskazuje

  • +: zmiany etapowe
  • *: zmiany niestacjonarne
  • _: nieśledzone pliki / foldery

Jak mogę sprawdzić, czy któryś z nich ma zmiany do scalenia?

Nazwy gałęzi są pokolorowane na 5 sposobów

  • biały: oddział lokalny nie ma oddziału zdalnego
  • zielony: oddział lokalny jest taki sam jak oddział zdalny
  • czerwony: oddział lokalny oddzielił się od oddziału zdalnego
  • fioletowy: oddział lokalny wyprzedza oddział zdalny (nadaje się do wypychania)
  • żółty: lokalny oddział znajduje się za zdalnym oddziałem (dobry do scalenia)

Aby go zainstalować, po prostu uruchom

pip3 install -U gita
nr
źródło
2

Jeśli ktoś nadal przegląda ten wątek, sprawdź mój skrypt powłoki o nazwie gitme

będziesz musiał ręcznie wprowadzić lokalne repozytoria git, ale używam tego narzędzia codziennie do współpracy z wieloma projektami git na wielu komputerach.

możesz biec git clone https://github.com/robbenz/gitme.git

również skrypt jest zamieszczony poniżej

#!/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

Ustawiam alias w moim ~ / .bash_profile, więc alias gitme='sh /path/to/gitme.sh'

RobBenz
źródło
1

Powinieneś sprawdzić rgit w CPAN, który rekurencyjnie wykonuje polecenia git we wszystkich repozytoriach w drzewie katalogów.

Z dokumentów:

To narzędzie rekurencyjnie przeszukuje katalog główny (który może być bieżącym katalogiem roboczym lub - jeśli został ustawiony - katalog podany przez zmienną środowiskową GIT_DIR) dla wszystkich repozytoriów git, sortuj tę listę według ścieżki repozytorium, chdir do każdego z je i wykonuje określone polecenie git.

Brian Phillips
źródło
1

Właśnie stworzyłem narzędzie, które robi, co chcesz!

  1. Jak mogę je wszystkie pobrać? gmaster fetch
  2. Jak mogę sprawdzić, czy któryś z nich ma niezatwierdzone zmiany? gmaster status
  3. Jak mogę sprawdzić, czy któryś z nich ma zmiany do scalenia? gmaster status

Nazywa się gitmaster: https://github.com/francoiscabrol/gitmaster

francoiscabrol
źródło
1

Napisałem tę prostą funkcję bash do mojego .bash_profile, aby móc uruchomić git, maven, gradle lub dowolne inne polecenie bash tylko we wszystkich repozytoriach 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
}

Można to wykorzystać w ten sposób

all git st
all git pull
all ./gradlew clean test
etc.
ChaudPain
źródło
można też uruchomić je wszystkie równolegle, używając: all './gradlew clean test &'
ChaudPain
0

Zastrzeżenie: pracuję nad tym narzędziem pod adresem www.repoflow.com

Jak mogę je wszystkie pobrać?
Jak mogę sprawdzić, czy któryś z nich ma zmiany do scalenia?

  • Możesz pobrać wszystkie zaangażowane repozytoria (lub wypchnąć / pociągnąć / zatwierdzić je), po pobraniu interfejs użytkownika zostanie zaktualizowany o nowy stan repozytorium, jeśli repozytorium jest rozbieżne, możesz zobaczyć rodzaj konfliktów i rozpocząć ich scalanie.

wprowadź opis obrazu tutaj

Jak mogę sprawdzić, czy któryś z nich ma niezatwierdzone zmiany?

  • W interfejsie użytkownika możesz zobaczyć stan plików dla każdego repozytorium (możesz je dodawać / usuwać pojedynczo lub zbiorczo).

wprowadź opis obrazu tutaj

Pracuję nad tym, ale jest to również rozwiązywanie pytań dotyczących OP i ogólnie pomoc w zarządzaniu wieloma repozytoriami. Możesz użyć interfejsu użytkownika lub bazowego interfejsu API GraphQL do tworzenia własnych skryptów, rozważ to jako inną opcję.

Victor Jimenez
źródło
0

Jest przydatne narzędzie do pobierania wszystkich wielu repozytoriów. git-pull-allto narzędzie wiersza poleceń do wykonywania na wielu repozytoriach git asynchronicznie.

Instalacja

npm install -g git-pull-all

Stosowanie

Załóżmy, że masz te pliki i katalogi:

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

Kiedy uruchamiasz git-pull-allpolecenie w ~/Projectskatalogu, powinno ono znaleźć repozytoria potomne git (w powyższym przypadku cool-examples i super-express ), a następnie wykonać git pullna każdym z nich.

$ 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

Łącze GitHub: https://github.com/tatsuyaoiw/git-pull-all

Alper Ebicoglu
źródło
0

Używam kodu Visual Studio. Mamy około 20 bibliotek w naszej bazie kodu, z których wszystkie są oddzielnymi repozytoriami Git, a karta kontroli źródła w programie Visual Studio Code jest całkiem dobra, aby zobaczyć „na pierwszy rzut oka”, jak daleko w tyle lub przed lokalnymi repozytoriami są. Istnieją również ustawienia okresowego pobierania, aby informacje były aktualne, a także przycisk odświeżania.

Nie jest to tak wygodne, jak skrypt, ale jeśli chodzi o kontrolę źródła, to lubię być tym, który wprowadza zmiany. Potrzeba bardzo dobrze napisanego skryptu, aby uważać, aby nie nadpisać zmian itp. Dzięki podejściu VS Code szybko uzyskujesz dużą ilość informacji, które możesz wykorzystać samodzielnie.

Oto zrzut ekranu, jak to wygląda:

Okno kontroli źródła w VS Code

Ty Deuty
źródło
0

Znalazłem świetne rozwiązanie do pobierania z bieżącej gałęzi ze wszystkich podkatalogów, które mają folder .git, nawet jeśli każde repozytorium ma wyewidencjonowaną inną gałąź. Polecenie jest jednolinijkowe, na tyle elastyczne, że można je modyfikować dla różnych poleceń git i można je aliasować.

Po prostu skopiuj i wklej następujące elementy:

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

Rozbijając to:

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

Znajdź wszystkie katalogi (-type d) w bieżącym katalogu (find.), Które mają nazwę „.git” (-name .git), szukając maksymalnie dwóch katalogów w głąb (2 zamiast 1, ponieważ szukamy git w folderze repo git).

-exec sh -c 

Uruchom następujące polecenie powłoki (exec sh -c)

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

Zmień katalog na pierwszy argument (cd $ 0), następnie zmień katalog o jeden poziom wyżej, aby opuścić folder .git (cd ..), a następnie wykonaj polecenie git pull origin podczas określania gałęzi, uruchamiając git rev-parse ... dla bieżącej gałęzi Zatwierdź HEAD.

{} \;

„{}” To ścieżka względna wyniku, którą otrzymujemy z początkowego znalezienia polecenia . The; służy do zakończenia polecenia.

Testowano na MacOS 10.14.6 na zsh. Tak jak jest, działa tylko wtedy, gdy zdalne i lokalne oddziały mają taką samą nazwę, AFAIK.

Możesz to zmienić, aby uzyskać status. Spodziewam się, że możesz dodać argumenty, aby uczynić to bardziej elastycznym, ale jeszcze nie próbowałem.

Ahmed Tawfik
źródło
-1

https://github.com/wwjamieson3/envisionTools ma skrypt bash o nazwie gitstat, który robi to i wiele więcej. Jest kompatybilny z GNU i Mac. Jeśli zostaniesz o to poproszony, może wykonać pobieranie z pilotów. Pokazuje nieśledzone, zmodyfikowane, dodane, usunięte i przemieszczone pliki. Różni się od pilotów, pokazując niezintegrowane zatwierdzenia na pilotach i niezakończone zatwierdzenia lokalne. Może również wyświetlać wyniki oznaczone kolorami w trybie podsumowania lub szczegółowym, a nawet HTML. Używa locate zamiast find, ponieważ jest nieskończenie szybszy, a nawet monituje o aktualizację bazy danych lokalizowania, jeśli stanie się zbyt stara.

William Jamieson
źródło
2
Dziękujemy za przesłanie odpowiedzi! Przeczytaj uważnie często zadawane pytania dotyczące autopromocji . Należy również pamiętać, że jest to konieczne , aby umieścić disclaimer każdym razem, gdy odwołują się do swojej własnej strony / produktu.
Andrew Barber
3
Niestety, link github wwjamieson3 / envisionTools jest uszkodzony.
Brenda J. Butler
@williamJamieson czy envisionTools to prywatne repozytorium GitHub?
eebbesen
-5

Wygląda na to, że napisanie scenariusza, który to zrobi, jest dość łatwe. Zasadniczo musi iterować repozytoria, a następnie używać poleceń takich jak git ls-files, git diff i git log.

iny
źródło
Wiem, że jest późno, ale czy mógłbyś opublikować scenariusz?
l0b0
Nie ma „scenariusza”. Używam skryptu, który napisałem na własne potrzeby, ale nie jest on ogólny.
iny
„git diff” jest właściwie trudne, jeśli chcesz uzyskać pojedynczy plik różnic, który można przywrócić i ponownie zastosować za pomocą jednego polecenia łatki.
proski
4
Dosłownie każda z odpowiedzi powinna być akceptowaną odpowiedzią, ale to.
Kennet Celeste