Gestire molti repository git


87

Impostare un progetto è facile in git e quindi posso avere un repository separato anche per piccoli script. Ora il problema è come gestirli.

Lavoro in più posti con questi repository. Quando ho apportato modifiche ad alcuni repository, voglio essere in grado di aggiornare i repository in altri luoghi.

Quindi ho una directory con molti repository al suo interno.

  1. Come posso recuperarli tutti?
  2. Come posso verificare se qualcuno di loro ha modifiche non salvate?
  3. Come posso verificare se qualcuno di loro ha modifiche da unire?

E sarebbe bello poterli fare con un comando.

L'output deve essere sufficientemente silenzioso per notare effettivamente le cose da fare.


La stessa domanda ha risposto per hg mercurial.
Serge Stroobandt

Uso la funzione di selezione multi-cursore / modifica su più righe del mio editor di codice (codice VS) per creare script batch / shell ed eseguirlo in una volta. Con questa semplice stupida soluzione, so cosa sto facendo e cosa posso aspettarmi dall'esecuzione di quei comandi. Nessuna supposizione, nessun apprendimento, nessuna personalizzazione necessaria. Un altro motivo è che ogni volta che voglio eseguire comandi su diversi set di repository che risiedono in una directory padre comune.
IsmailS

Risposte:


45

Consiglio vivamente lo strumento di repository multipli mr . Per un po 'di tempo usavo uno script di shell personalizzato come consigliato da altri, ma l'uso di mr ha i seguenti vantaggi per me:

  • È generico: è possibile utilizzare una combinazione di vari sistemi di controllo della versione, non solo git (ad esempio Mercurial, SVN, ecc.).
  • È veloce: mr può eseguire più lavori in parallelo. Uso diversi repository git / mercurial e li sincronizzo più volte al giorno. Il signor accelera enormemente questo processo.
  • È facile e veloce gestire l'elenco dei checkout del repository. Usa semplicemente "mr register" invece di modificare l'elenco dei progetti nel tuo script personalizzato.

Per quanto riguarda la tua domanda sull'output silenzioso: il livello di verbosità può essere modificato utilizzando l'opzione della riga di comando -q. Preferisco l'output predefinito che sembra unificare bene l'output in un breve e chiaro riepilogo.

Uso il seguente alias per il comando mr per assicurarmi che mr prenda sempre il mio elenco di progetti predefinito memorizzato in $ HOME e utilizzi 5 thread paralleli:

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

è fantastico ma non supporta il tagging git (al 2016-08)
Hugo Zaragoza

@CADbloke non menziona finestre nella pagina di installazione, ma come script Perl potrebbe / dovrebbe / potrebbe funzionare su Windows.
scipilot

2
@HugoZaragoza, puoi sempre definire questo comando da solo [DEFAULT] tag = git tag "$ @"
AlexS

2
alias pa='find . -name .git -print -execdir git pull \;'quindi, paè sufficiente
DawnSong

19

Devo dire che ho iniziato con la risposta attualmente accettata (solo un gruppo di script di helper che iterano sui repository), ma tutto sommato, è stata un'esperienza mancante per me.

Quindi, dopo aver provato mr, repo e git-submodules, ho riscontrato che ciascuno mancava in un modo diverso, quindi ho finito per fare la mia variante: http://fabioz.github.io/mu-repo che è uno strumento maturo su questo punto - ha flussi di lavoro che ti consentono di:

  • clonare più repository
  • diff (e modifica) le modifiche correnti in più repository
  • visualizzare in anteprima le modifiche in arrivo
  • eseguire comandi in più repository in parallelo
  • creare gruppi di pronti contro termine
  • eseguire comandi non correlati a git su più repository
  • ecc (vedere la homepage per maggiori informazioni).

Nota che supporta qualsiasi sistema operativo in cui viene eseguito Python;)


La tua risposta suggerisce che mu-repo è migliore di quello che fa mr. Ma mu-repo non supporta i repository non git.
Shaunak Sontakke

1
Whell, il suo scopo è davvero quello di supportare solo i repository git (che è ciò che la domanda posta) - sebbene tu possa fare mu sh <some command>per eseguire alcuni comandi arbitrari anche in più repository, la sua intera finalità è trattare git e non altri sistemi di controllo della versione .. se ne hai bisogno, allora sì, usa uno strumento diverso.
Fabio Zadrozny

14

gr (git-run) estendele funzionalità di mr (solo pergit). Trovo più facile organizzare più repository Git utilizzando il suo sistema di tag. Il codice pergrnon è ben mantenuto però. Se stai usando bash, assicurati di usarlo con-t taginvece di#tagform.


Sembra che lo sviluppo abbia ripreso un po 'da allora: github.com/mixu/gr/graphs/contributors
Dave Forgac

8

Potresti provare a utilizzare repo con un manifest.xmlfile personalizzato per specificare dove si trovano i tuoi repository. C'è della documentazione su come farlo.

In alternativa potresti usare git-submodule(1) .


2
git-submodule sarebbe buono, se volessi mantenere i repository nello stesso identico stato, ma non è così. L'insieme dei repository non è lo stesso in ogni luogo. Potrebbero esserci modifiche non confermate. Potrebbero esserci modifiche che non voglio ancora unire.
iny

Non sapevo del sottomodulo git. Grazie per averlo menzionato.
sykora

La documentazione per il repo è piuttosto minima e sembra che sia destinata a diversi tipi di flusso di lavoro che voglio utilizzare.
iny

6

Ho scritto uno strumento chiamato " RepoZ " che scopre automaticamente i repository git non appena li cloni o modifichi qualcosa in essi, ad esempio cambiare un ramo.

Una volta trovati, i repository vengono "tracciati". Questo li mostrerà semplicemente in un elenco di repository locali, inclusa una densa informazione sullo stato ispirata a posh-git . Questo contiene il ramo corrente e altre cose come le modifiche ai file e il conteggio dei commit in entrata o in uscita.

RepoZ UI

Questo aiuta a tenere traccia dei tuoi repository locali e del lavoro incompiuto di cui eseguire il commit o il push. Inoltre, è possibile utilizzare l'elenco dei repository come navigazione per passare da un repository a un altro.

Navigazione RepoZ

"Come posso recuperarli tutti?"

La versione per Windows offre un menu contestuale per recuperare o estrarre un repository. Con la selezione multipla puoi eseguire azioni su più repository contemporaneamente.

Tuttavia, potresti trovare un'altra funzionalità molto utile:

RepoZ Auto-Fetch

Con il recupero automatico, puoi dire a RepoZ di recuperare i telecomandi di tutti i tuoi repository git periodicamente in background. Naturalmente, questi recuperi non entreranno in conflitto con i commit locali. Non ci sono tentativi di unione locale come con git pull.


Già, peccato e non meritato. Aperto per PR in qualsiasi momento. Me il ping.
Waescher

5

gitslave è uno strumento che può eseguire lo stesso comando su molti repository creando una relazione superprogetto / sottoprogetto tra super e sub. Questo (per impostazione predefinita) fornisce il riepilogo dell'output in modo che tu possa concentrarti sui repository che forniscono un output unico (utile per git status, non così utile per git ls-files).

Questo è in genere utilizzato per progetti in cui è necessario assemblare più repository insieme e mantenerli sullo stesso ramo o tag contemporaneamente o altro. Per la mia directory di repository (nudi) ho solo un piccolo makefile che mi consente di eseguire comandi git arbitrari, che come vedete io uso principalmente per fsck e 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

Ho creato un alias e una funzione per eseguire qualsiasi comando git su tutti i repository disponibili in una directory (in modo ricorsivo). Puoi trovarlo qui: https://github.com/jaguililla/dotfiles/git

Questo è il codice:

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

Spero che sia d'aiuto :)


1
sottile e utile!
Kevin Chou

Fantatstic! Semplice one-liner per mettere in .bash_aliases: alias rgit='function _rgit(){ find . -type d -name .git -printf "\n%p\n" -execdir git "$@" \;; }; _rgit'. Fonte, quindi ad esempio chiama rgit status.
ford04

4

Puoi usare la git-status-allgemma per questo: 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

C'è anche un'opzione di recupero che recupererà dall'origine per tutti i repository prima di visualizzare lo stato:

git status-all --fetch

git status all


1
Approccio molto carino. In contrasto con la maggior parte degli strumenti più votati, non è necessario prima registrare i repository, ma controlla semplicemente tutte le sottodirectory.
luator

find . -name .git -print -execdir git status \;va bene
DawnSong

3

Uso questo script per eseguire facilmente i comandi git in tutti i miei repository.

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

Per impostazione predefinita, lo script cercherà i repository git in ~ / cm / src ma puoi sovrascriverlo impostando la variabile d'ambiente GITREPO a tuo piacimento.

Questo script è basato su questo script .


find . -name .git -print -execdir git pull \;fa quello che pensi.
DawnSong

3

Ho scritto uno strumento a riga di comando chiamato gita per gestire più repository. Ad esempio, mostra lo stato dei pronti contro termine registrati fianco a fianco

inserisci qui la descrizione dell'immagine

Può anche delegare comandi / alias git da qualsiasi directory di lavoro.

Ora per rispondere alle tue domande usando questo strumento:

Come posso recuperarli tutti?

gita fetch

Come posso verificare se qualcuno di loro ha modifiche non salvate?

Il gita lscomando mostra 3 possibili simboli accanto al nome del ramo, che indica

  • +: modifiche in scena
  • *: modifiche non messe in scena
  • _: file / cartelle non tracciati

Come posso verificare se qualcuno di loro ha modifiche da unire?

I nomi dei rami sono colorati in 5 modi

  • bianco: il ramo locale non ha un ramo remoto
  • verde: il ramo locale è lo stesso del ramo remoto
  • rosso: il ramo locale si è discostato dal ramo remoto
  • viola: il ramo locale è davanti al ramo remoto (buono per push)
  • giallo: il ramo locale è dietro il ramo remoto (buono per l'unione)

Per installarlo, è sufficiente eseguire

pip3 install -U gita

2

Se qualcuno sta ancora guardando questo thread, controlla il mio script di shell chiamato gitme

dovrai inserire manualmente i tuoi repository git locali, ma io uso questo strumento tutti i giorni per collaborare a più progetti git su più computer.

puoi correre git clone https://github.com/robbenz/gitme.git

anche lo script è pubblicato di seguito

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

Ho impostato un alias nel mio ~ / .bash_profile così alias gitme='sh /path/to/gitme.sh'


1

Dovresti controllare rgit sul CPAN che esegue ricorsivamente i comandi git su tutti i repository in un albero di directory.

Dai documenti:

Questa utility cerca ricorsivamente in una directory root (che può essere la directory di lavoro corrente o - se è stata impostata - la directory data dalla variabile d'ambiente GIT_DIR) per tutti i repository git, ordina questo elenco in base al percorso del repository, chdir in ciascuno di loro ed esegue il comando git specificato.


1

Ho appena creato uno strumento che fa quello che vuoi!

  1. Come posso recuperarli tutti? gmaster fetch
  2. Come posso verificare se qualcuno di loro ha modifiche non salvate? gmaster status
  3. Come posso verificare se qualcuno di loro ha modifiche da unire? gmaster status

Si chiama gitmaster: https://github.com/francoiscabrol/gitmaster


1

Ho scritto questa semplice funzione bash nel mio .bash_profile per poter eseguire git, maven, gradle o qualsiasi altro comando bash solo in tutti i repository 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
}

Questo può essere usato in questo modo

all git st
all git pull
all ./gradlew clean test
etc.

si potrebbe anche eseguirli tutti in parallelo usando: all './gradlew clean test &'
ChaudPain

0

Dichiarazione di non responsabilità: sto lavorando a questo strumento su www.repoflow.com

Come posso recuperarli tutti?
Come posso verificare se qualcuno di loro ha modifiche da unire?

  • Puoi recuperare tutti i repository coinvolti (o push / pull / commit), dopo il fetch l'interfaccia utente verrà aggiornata con il nuovo stato del repository, se il repository è divergente puoi vedere il tipo di conflitti e iniziare a unirli.

inserisci qui la descrizione dell'immagine

Come posso verificare se qualcuno di loro ha modifiche non salvate?

  • Sull'interfaccia utente puoi vedere lo stato dei file per ogni repository (puoi aggiungerli / rimuoverli singolarmente o in blocco).

inserisci qui la descrizione dell'immagine

Sto lavorando su questo, ma questo sta anche risolvendo le domande OP e aiuta a gestire più repository in generale, puoi utilizzare l'interfaccia utente o l'API GraphQL sottostante per creare i tuoi script, consideralo come un'altra opzione.


0

C'è uno strumento utile per recuperare tutti i più repository. git-pull-allè uno strumento a riga di comando da eseguire su più repository Git in modo asincrono.

Installazione

npm install -g git-pull-all

Utilizzo

Supponi di avere questi file e directory:

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

Quando esegui il git-pull-allcomando sulla ~/Projectsdirectory, dovrebbe trovare repository git figlio (nel caso sopra cool-examples e super-express ) quindi eseguirlo git pullsu ciascuno di essi.

$ 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

Collegamento GitHub: https://github.com/tatsuyaoiw/git-pull-all


0

Uso il codice di Visual Studio. Abbiamo circa 20 librerie nella nostra base di codice che sono tutti repository Git separati e la scheda del controllo del codice sorgente in Visual Studio Code è abbastanza buona per vedere una vista "a colpo d'occhio" di quanto sono indietro o avanti i repository locali. Ci sono anche impostazioni da recuperare periodicamente per mantenere aggiornate le informazioni, oltre a un pulsante di aggiornamento.

Non è comodo come uno script, ma quando si tratta di controllo del codice sorgente per me mi piace essere quello che apporta le modifiche. Ci vuole uno script ben scritto per fare attenzione a non sovrascrivere le modifiche, ecc. Con l'approccio VS Code, si ottiene rapidamente una buona quantità di informazioni che è possibile agire su se stessi.

Ecco uno screenshot di come appare:

Finestra di controllo del codice sorgente in VS Code


0

Ho trovato un'ottima soluzione per estrarre dal ramo corrente da tutte le sottodirectory che hanno una cartella .git, anche se ogni repository ha un ramo diverso estratto. Il comando è di una riga, abbastanza flessibile da modificare per diversi comandi git e può essere alias.

Basta copiare e incollare quanto segue:

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

Abbattendolo:

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

Trova tutte le directory (-type d) nella directory corrente (find.) Che hanno il nome ".git" (-name .git), cercando un massimo di due directory in profondità (2 anziché 1 perché stiamo cercando il git nella cartella git repo).

-exec sh -c 

Esegui il seguente comando di shell (exec sh -c)

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

Cambia directory al primo argomento (cd $ 0), quindi cambia directory di un livello in alto per lasciare la cartella .git (cd ..) quindi esegui git pull origin specificando il ramo eseguendo git rev-parse ... per il ramo corrente HEAD commit.

{} \;

"{}" È il percorso relativo del risultato ottenuto dal comando find iniziale . Il ; viene utilizzato per terminare il comando.

Testato su MacOS 10.14.6 su zsh. Così com'è, funziona solo quando i rami remoti e locali hanno lo stesso nome, AFAIK.

Puoi modificarlo per ottenere lo stato. Mi aspetto che tu possa aggiungere argomenti per renderlo ulteriormente più flessibile, ma non ho ancora provato.


0

Uso la funzione di selezione multi-cursore / modifica su più righe del mio editor di codice (codice VS) per creare script batch / shell ed eseguirlo in una volta. Con questa semplice stupida soluzione, so cosa sto facendo e cosa posso aspettarmi dall'esecuzione di quei comandi. Nessuna supposizione, nessun apprendimento, nessuna personalizzazione necessaria. Un altro motivo è che ogni volta che voglio eseguire comandi su diversi set di repository che risiedono in una directory padre comune.


-1

https://github.com/wwjamieson3/envisionTools ha uno script bash chiamato gitstat che fa questo e molto altro ancora. È compatibile con GNU e Mac. Può eseguire recuperi dai telecomandi se richiesto. Mostra file non tracciati, modificati, aggiunti, eliminati e gestiti. Differisce dai telecomandi mostrando commit non uniti sui telecomandi e commit locali non premuti. Può anche visualizzare i risultati codificati a colori in modalità riepilogativa o dettagliata e persino HTML. Utilizza la localizzazione anziché la ricerca perché è infinitamente più veloce e richiederà persino di aggiornare il database di individuazione se sta diventando troppo vecchio.


2
Grazie per aver pubblicato la tua risposta! Assicurati di leggere attentamente le FAQ sull'autopromozione . Si noti inoltre che è necessario pubblicare un disclaimer ogni volta che si collega al proprio sito / prodotto.
Andrew Barber

3
Sfortunatamente, il collegamento github wwjamieson3 / visionTools è interrotto.
Brenda J. Butler

@williamJamieson is exploreTools è un repository GitHub privato?
eebbesen,

-5

Sembra che scrivere una sceneggiatura per farlo sia abbastanza facile. Essenzialmente ha bisogno di iterare sui repository e quindi utilizzare comandi come git ls-files, git diff e git log.


So che è tardi, ma potresti pubblicare la sceneggiatura?
l0b0

Non esiste "lo script". Sto usando uno script che ho scritto per le mie esigenze, ma non è generico.
iny

"git diff" è effettivamente complicato se si desidera ottenere un singolo file diff che può essere ripristinato e riapplicato con un singolo comando patch.
proski

4
Letteralmente qualsiasi risposta dovrebbe essere la risposta accettata ma questa.
Kennet Celeste
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.