annulla il sottomodulo di un sottomodulo git


378

Come posso annullare la sottomodulazione di un sottomodulo git (riportare tutto il codice nel core)?

Come in "dovrei" io, come in "Migliore procedura" ...


5
Nota: con git1.8.3, ora puoi provare a git submodule deinit, vedi la mia risposta di seguito
VonC

6
Potrei fraintendere, ma git submodule deinit sembra rimuovere il codice.
Joe Germuska,

2
Da git 1.8.5 (novembre 2013), git submodule deinit asubmodule ; git rm asubmoduleè sufficiente un semplice , come illustrato nella mia risposta di seguito
VonC

considerare l'utilizzo di git sotto-albero
HiB

Risposte:


527

Se tutto ciò che desideri è inserire il codice del tuo sottomodulo nel repository principale, devi solo rimuovere il sottomodulo e aggiungere nuovamente i file nel repository principale:

git rm --cached submodule_path # delete reference to submodule HEAD (no trailing slash)
git rm .gitmodules             # if you have more than one submodules,
                               # you need to edit this file instead of deleting!
rm -rf submodule_path/.git     # make sure you have backup!!
git add submodule_path         # will add files instead of commit reference
git commit -m "remove submodule"

Se vuoi anche preservare la cronologia del sottomodulo, puoi fare un piccolo trucco: "unisci" il sottomodulo nel repository principale in modo che il risultato sia lo stesso di prima, tranne che i file del sottomodulo sono ora nella repository principale.

Nel modulo principale dovrai fare quanto segue:

# Fetch the submodule commits into the main repository
git remote add submodule_origin git://url/to/submodule/origin
git fetch submodule_origin

# Start a fake merge (won't change any files, won't commit anything)
git merge -s ours --no-commit submodule_origin/master

# Do the same as in the first solution
git rm --cached submodule_path # delete reference to submodule HEAD
git rm .gitmodules             # if you have more than one submodules,
                               # you need to edit this file instead of deleting!
rm -rf submodule_path/.git     # make sure you have backup!!
git add submodule_path         # will add files instead of commit reference

# Commit and cleanup
git commit -m "removed submodule"
git remote rm submodule_origin

Il repository risultante sembrerà un po 'strano: ci sarà più di un commit iniziale. Ma non causerà alcun problema per Git.

In questa seconda soluzione avrai il grande vantaggio di poter ancora eseguire git blame o git log sui file originariamente presenti nei sottomoduli. In effetti quello che hai fatto qui è stato rinominare molti file all'interno di un repository e git dovrebbe rilevare automaticamente questo. Se hai ancora problemi con git log, prova alcune opzioni (--follow, -M, -C) che migliorano il rinominare / copiare il rilevamento.


3
Penso di dover fare il tuo secondo metodo (preservare la storia) su alcuni repository git che ho. Potresti spiegare quale parte dei comandi sopra fa sì che i file dal sottomodulo finiscano nella sottodirectory? Sei tu quando esegui l'unione git porta il file nella directory di livello superiore (con la sua cronologia) ma quando fai git aggiungi submodule_path, implicitamente fa un git mv per ogni file?
Bowie Owens il

5
Fondamentalmente sì. Il trucco è che git non memorizza le operazioni di rinomina: invece le rileva osservando i commit dei genitori. Se è presente un contenuto file presente nel commit precedente, ma con un nome file diverso, viene considerato un nome (o una copia). Nei passaggi precedenti, git mergeassicurati che ci sia un "commit precedente" per ogni file (su uno dei due "lati" della fusione).
Gyim,

6
Grazie, ho iniziato un progetto in cui ho pensato che fosse logico dividere le cose in un paio di repository e collegarli di nuovo con i sottomoduli. Ma ora sembra troppo ingegnerizzato e voglio combinarli di nuovo insieme senza perdere la mia storia.
Bowie Owens,

4
@theduke Ho avuto anche questo problema. Può essere risolto prima di seguire questi passaggi, spostando tutti i file dal repository dei sottomoduli in una struttura di directory con lo stesso percorso del repository in cui si sta per unire: ad es. se il tuo sottomodulo nel repository principale è in foo /, nel sottomodulo, esegui mkdir foo && git mv !(foo) foo && git commit.
Chris Down,

35
--allow-unrelated-historiesHo dovuto aggiungere per forzare l'unione alla falsa unione mentre stavo ottenendo fatal: refusing to merge unrelated histories, di più qui: github.com/git/git/blob/master/Documentation/RelNotes/…
vaskort

72

Da git 1.8.5 (novembre 2013 ) ( senza mantenere la cronologia del sottomodulo ):

mv yoursubmodule yoursubmodule_tmp
git submodule deinit yourSubmodule
git rm yourSubmodule
mv yoursubmodule_tmp yoursubmodule
git add yoursubmodule

Quello sarà:

  • annullare la registrazione e scaricare (ovvero eliminare il contenuto di ) il sottomodulo ( deinit, quindi il mv primo ),
  • ripulisci il .gitmodulesfor you ( rm),
  • e rimuovere la voce speciale che rappresenta quel sottomodulo SHA1 nell'indice del repository principale ( rm).

Una volta completata la rimozione del sottomodulo ( deinite git rm), è possibile rinominare la cartella con il nome originale e aggiungerla al repository git come una normale cartella.

Nota: se il sottomodulo è stato creato da un vecchio Git (<1.8), potrebbe essere necessario rimuovere la .gitcartella nidificata all'interno del sottomodulo stesso, come commentato da Simon East


Se è necessario conservare la cronologia del sottomodulo, consultare la risposta di jsears , che utilizza .git filter-branch


5
Questo effettivamente lo elimina dall'albero di lavoro in 1.8.4 (la mia intera directory del sottomodulo è stata cancellata).
Chris Down,

@ChrisDown vuoi dire, il deinitsolo ha pulito l'albero di lavoro dal tuo sottomodulo?
VonC,

Sì, rimuove tutto il contenuto nella directory del sottomodulo.
Chris Down,

2
@mschuett no, non ti manca nulla: in primo luogo un sottomodulo non contiene .git. Se quello era il tuo caso, era un repository nidificato, non un sottomodulo. Questo spiega perché questa risposta sopra non si applicherebbe al tuo caso. Per la differenza tra i due, consultare stackoverflow.com/a/34410102/6309 .
VonC

1
@VonC Sono attualmente su 2.9.0.windows.1, tuttavia i sottomoduli potrebbero essere stati creati diversi anni fa su una versione molto precedente di git, non ne sono sicuro. Penso che i passaggi sembrano funzionare fintanto che rimuovo quel file prima di fare l'ultimo add + commit.
Simon East,

67

Ho creato uno script che tradurrà un sottomodulo in una semplice directory, pur mantenendo tutta la cronologia dei file. Non soffre dei git log --follow <file>problemi di cui soffrono le altre soluzioni. È anche una semplice chiamata a una riga che fa tutto il lavoro per te. G'luck.

Si basa sull'eccellente lavoro di Lucas Jenß, descritto nel suo post sul blog " Integrazione di un sottomodulo nel repository principale ", ma automatizza l'intero processo e ripulisce alcuni altri casi angolari.

L'ultimo codice verrà mantenuto con correzioni di bug su github all'indirizzo https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite , ma per motivi di protocollo di risposta stackoverflow corretto, ho incluso il soluzione nella sua interezza di seguito.

Uso:

$ git-submodule-rewrite <submodule-name>

git-modulo-riscrivere:

#!/usr/bin/env bash

# This script builds on the excellent work by Lucas Jenß, described in his blog
# post "Integrating a submodule into the parent repository", but automates the
# entire process and cleans up a few other corner cases.
# https://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html

function usage(){
  echo "Merge a submodule into a repo, retaining file history."
  echo "Usage: $0 <submodule-name>"
  echo ""
  echo "options:"
  echo "  -h, --help                Print this message"
  echo "  -v, --verbose             Display verbose output"
}

function abort {
    echo "$(tput setaf 1)$1$(tput sgr0)"
    exit 1
}

function request_confirmation {
    read -p "$(tput setaf 4)$1 (y/n) $(tput sgr0)"
    [ "$REPLY" == "y" ] || abort "Aborted!"
}

function warn() {
  cat << EOF
    This script will convert your "${sub}" git submodule into
    a simple subdirectory in the parent repository while retaining all
    contents and file history.

    The script will:
      * delete the ${sub} submodule configuration from .gitmodules and
        .git/config and commit it.
      * rewrite the entire history of the ${sub} submodule so that all
        paths are prefixed by ${path}.
        This ensures that git log will correctly follow the original file
        history.
      * merge the submodule into its parent repository and commit it.

    NOTE: This script might completely garble your repository, so PLEASE apply
    this only to a fresh clone of the repository where it does not matter if
    the repo is destroyed.  It would be wise to keep a backup clone of your
    repository, so that you can reconstitute it if need be.  You have been
    warned.  Use at your own risk.

EOF

  request_confirmation "Do you want to proceed?"
}

function git_version_lte() {
  OP_VERSION=$(printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4))
  GIT_VERSION=$(git version)
  GIT_VERSION=$(printf "%03d%03d%03d%03d" $(echo "${GIT_VERSION#git version}" | tr '.' '\n' | head -n 4))
  echo -e "${GIT_VERSION}\n${OP_VERSION}" | sort | head -n1
  [ ${OP_VERSION} -le ${GIT_VERSION} ]
}

function main() {

  warn

  if [ "${verbose}" == "true" ]; then
    set -x
  fi

  # Remove submodule and commit
  git config -f .gitmodules --remove-section "submodule.${sub}"
  if git config -f .git/config --get "submodule.${sub}.url"; then
    git config -f .git/config --remove-section "submodule.${sub}"
  fi
  rm -rf "${path}"
  git add -A .
  git commit -m "Remove submodule ${sub}"
  rm -rf ".git/modules/${sub}"

  # Rewrite submodule history
  local tmpdir="$(mktemp -d -t submodule-rewrite-XXXXXX)"
  git clone "${url}" "${tmpdir}"
  pushd "${tmpdir}"
  local tab="$(printf '\t')"
  local filter="git ls-files -s | sed \"s/${tab}/${tab}${path}\//\" | GIT_INDEX_FILE=\${GIT_INDEX_FILE}.new git update-index --index-info && mv \${GIT_INDEX_FILE}.new \${GIT_INDEX_FILE}"
  git filter-branch --index-filter "${filter}" HEAD
  popd

  # Merge in rewritten submodule history
  git remote add "${sub}" "${tmpdir}"
  git fetch "${sub}"

  if git_version_lte 2.8.4
  then
    # Previous to git 2.9.0 the parameter would yield an error
    ALLOW_UNRELATED_HISTORIES=""
  else
    # From git 2.9.0 this parameter is required
    ALLOW_UNRELATED_HISTORIES="--allow-unrelated-histories"
  fi

  git merge -s ours --no-commit ${ALLOW_UNRELATED_HISTORIES} "${sub}/master"
  rm -rf tmpdir

  # Add submodule content
  git clone "${url}" "${path}"
  rm -rf "${path}/.git"
  git add "${path}"
  git commit -m "Merge submodule contents for ${sub}"
  git config -f .git/config --remove-section "remote.${sub}"

  set +x
  echo "$(tput setaf 2)Submodule merge complete. Push changes after review.$(tput sgr0)"
}

set -euo pipefail

declare verbose=false
while [ $# -gt 0 ]; do
    case "$1" in
        (-h|--help)
            usage
            exit 0
            ;;
        (-v|--verbose)
            verbose=true
            ;;
        (*)
            break
            ;;
    esac
    shift
done

declare sub="${1:-}"

if [ -z "${sub}" ]; then
  >&2 echo "Error: No submodule specified"
  usage
  exit 1
fi

shift

if [ -n "${1:-}" ]; then
  >&2 echo "Error: Unknown option: ${1:-}"
  usage
  exit 1
fi

if ! [ -d ".git" ]; then
  >&2 echo "Error: No git repository found.  Must be run from the root of a git repository"
  usage
  exit 1
fi

declare path="$(git config -f .gitmodules --get "submodule.${sub}.path")"
declare url="$(git config -f .gitmodules --get "submodule.${sub}.url")"

if [ -z "${path}" ]; then
  >&2 echo "Error: Submodule not found: ${sub}"
  usage
  exit 1
fi

if ! [ -d "${path}" ]; then
  >&2 echo "Error: Submodule path not found: ${path}"
  usage
  exit 1
fi

main

Non funziona su Ubuntu 16.04. Ho inviato una richiesta pull al repository Github.
qznc,

1
Buona cattura, @qznc. Questo è stato testato su OSX. Li unirò felicemente quando passerà su entrambe le piattaforme.
jsears,

@qznc Supporto per Ubuntu 16.04 unito e risposta aggiornata.
jsears,

2
Questa è la risposta migliore, mantiene l'intera storia. Molto bella!
Charles B

1
Funziona tutto senza errori in Git Bash 2.20.1.1 su Windows 10 con l'ultima versione di github: curl https://raw.githubusercontent.com/jeremysears/scripts/master/bin/git-submodule-rewrite > git-submodule-rewrite.she./git-submodule-rewrite.sh <submodule-name>
Alexey,

32
  1. git rm --cached the_submodule_path
  2. rimuovere la sezione del sottomodulo dal .gitmodulesfile o, se è l'unico sottomodulo, rimuovere il file.
  3. eseguire un commit "xyz sottomodulo rimosso"
  4. git add the_submodule_path
  5. un altro commit "aggiunta base di codice di xyz"

Non ho ancora trovato un modo più semplice. Puoi comprimere 3-5 in un solo passaggio tramite git commit -a- questione di gusti.


6
Non dovrebbe essere .gitmodulesinvece di .submodules?
imz - Ivan Zakharyaschev,

1
Dovrebbe essere .gitmodulesnon.submodules
Mkey

1
Ho dovuto rimuovere la .gitdirectory del sottomodulo prima git addche funzionasse sulla cartella del sottomodulo
Carson Evans,

16

Molte risposte qui, ma tutte sembrano essere eccessivamente complesse e probabilmente non fanno quello che vuoi. Sono sicuro che molte persone vogliono mantenere la loro storia.

Per questo esempio il repository principale sarà git@site.com:main/main.gite il repository sottomodulo sarà git@site.com:main/child.git. Ciò presuppone che il sottomodulo si trovi nella directory principale del repository principale. Regola le istruzioni secondo necessità.

Inizia clonando il repository principale e rimuovendo il vecchio sottomodulo.

git clone git@site.com:main/main.git
git submodule deinit child
git rm child
git add --all
git commit -m "remove child submodule"

Ora aggiungeremo i repository secondari a monte al repository principale.

git remote add upstream git@site.com:main/child.git
git fetch upstream
git checkout -b merge-prep upstream/master

Il passaggio successivo presuppone che si desideri spostare i file sul ramo di preparazione-unione nella stessa posizione del sottomodulo precedente, sebbene sia possibile modificare facilmente la posizione modificando il percorso del file.

mkdir child

sposta tutte le cartelle e tutti i file tranne la cartella .git nella cartella secondaria.

git add --all
git commit -m "merge prep"

Ora puoi semplicemente unire nuovamente i tuoi file nel ramo principale.

git checkout master
git merge merge-prep # --allow-unrelated-histories merge-prep flag may be required 

Guardati intorno e assicurati che tutto appaia bene prima di correre git push

L'unica cosa che devi ricordare ora è che git log non segue di default i file spostati, ma eseguendo git log --follow filenamepuoi vedere la cronologia completa dei tuoi file.


2
Sono arrivato in finale git merge merge-prepe ho ricevuto l'errore fatal: refusing to merge unrelated histories. Soluzione è questo: git merge --allow-unrelated-histories merge-prep.
Humblehacker,

@humblehacker grazie ho aggiunto un piccolo commento nel caso in cui anche altri si imbattano in questo.
mschuett,

1
La migliore risposta per mantenere la cronologia del sottomodulo. Grazie @mschuett
Anton Temchenko il

Nell'esempio qui, c'è un modo per recuperare i file dell'upstream nella childdirectory, quindi non è necessario spostarli in seguito? Ho gli stessi nomi di file in un sottomodulo e nel repository principale ... quindi ho solo un conflitto di unione poiché sta cercando di unire i due file insieme.
Skitterm

Forse, ma non lo so di persona. Personalmente farei semplicemente un commit spostando i file nel repository in cui stai provando a trasferirli in modo che risiedano nella directory desiderata prima di inserirli.
mschuett

12

Ci è successo che abbiamo creato 2 repository per 2 progetti che erano così accoppiati da non avere senso separarli, quindi li abbiamo uniti.

Mostrerò come unire prima i rami master in ciascuno e poi spiegherò come estenderlo a tutti i rami che hai, spero che ti aiuti.

Se il sottomodulo funziona e si desidera convertirlo in una directory in atto, è possibile:

git clone project_uri project_name

Qui facciamo un clone pulito per funzionare. Per questo processo non è necessario inizializzare o aggiornare i sottomoduli, quindi saltalo.

cd project_name
vim .gitmodules

Modifica .gitmodulescon il tuo editor preferito (o Vim) per rimuovere il sottomodulo che intendi sostituire. Le linee che devi rimuovere dovrebbero avere un aspetto simile al seguente:

[submodule "lib/asi-http-request"]
    path = lib/asi-http-request
    url = https://github.com/pokeb/asi-http-request.git

Dopo aver salvato il file,

git rm --cached directory_of_submodule
git commit -am "Removed submodule_name as submodule"
rm -rf directory_of_submodule

Qui rimuoviamo completamente la relazione del sottomodulo in modo da poter creare portare l'altro repository sul progetto sul posto.

git remote add -f submodule_origin submodule_uri
git fetch submodel_origin/master

Qui prendiamo il repository del sottomodulo da unire.

git merge -s ours --no-commit submodule_origin/master

Qui iniziamo un'operazione di unione dei 2 repository, ma ci fermiamo prima del commit.

git read-tree --prefix=directory_of_submodule/ -u submodule_origin/master

Qui inviamo il contenuto del master nel sottomodulo alla directory in cui si trovava prima del prefisso di un nome di directory

git commit -am "submodule_name is now part of main project"

Qui completiamo la procedura eseguendo il commit delle modifiche nell'unione.

Al termine, è possibile eseguire il push e ricominciare con qualsiasi altro ramo da unire, è sufficiente controllare il ramo nel proprio repository che riceverà le modifiche e modificare il ramo che si sta portando nelle operazioni di unione e lettura.


questo non sembra aver conservato la cronologia dei file del sottomodulo, vedo solo un singolo commit nel registro git per i file aggiunti indirectory_of_submodule
Anentropic

@Anentropic Ci scusiamo per il ritardo nella risposta. Ho appena eseguito di nuovo la procedura completa (con una piccola correzione). La procedura mantiene l'intera storia, ma ha un punto di unione, forse è per questo che non la trovi. Se vuoi vedere la cronologia del sottomodulo fai semplicemente un "log git", cerca il commit di merge (nell'esempio è quello con il messaggio "submodule_name è ora parte del progetto principale"). Avrà 2 commit genitore (Unisci: sdasda asdasd), git registra il secondo commit e lì hai tutto il tuo sottomodulo / storia principale.
dvicino

la mia memoria ora è confusa ma penso di essere stata in grado di ottenere la cronologia dei file del sottomodulo uniti facendo git log original_path_of_file_in_submodulecioè il percorso registrato nel repository git per il file (che non esiste più sul filesystem) anche se il file del sottomodulo ora vive allesubmodule_path/new_path_of_file
Anentropic

Questo non preserva molto bene la storia e anche i percorsi sono sbagliati. Sento che è necessario qualcosa come un filtro per alberi ma sono fuori dalla mia profondità ... provando quello che ho trovato qui: x3ro.de/2013/2013/01/01/…
Luca H

Questa risposta è obsoleto, stackoverflow.com/a/16162228/11343 (VonC risposta) fa la stessa cosa ma meglio
charlesb


6

Ecco una versione leggermente migliorata (IMHO) della risposta di @gyim. Sta facendo un mucchio di pericolose modifiche nella copia di lavoro principale, dove penso che sia molto più facile operare su cloni separati e poi unirli insieme alla fine.

In una directory separata (per rendere più semplici gli errori da ripulire e riprovare), controlla sia il repository superiore che il sottorepo.

git clone ../main_repo main.tmp
git clone ../main_repo/sub_repo sub.tmp

Prima modifica il sottorepo per spostare tutti i file nella sottodirectory desiderata

cd sub.tmp
mkdir sub_repo_path
git mv `ls | grep -v sub_repo_path` sub_repo_path/
git commit -m "Moved entire subrepo into sub_repo_path"

Prendi nota della TESTA

SUBREPO_HEAD=`git reflog | awk '{ print $1; exit; }'`

Rimuovere quindi il sottorepo dal repository principale

cd ../main.tmp
rmdir sub_repo_path
vi .gitmodules  # remove config for submodule
git add -A
git commit -m "Removed submodule sub_repo_path in preparation for merge"

E infine, uniscili

git fetch ../sub.tmp
# remove --allow-unrelated-histories if using git older than 2.9.0
git merge --allow-unrelated-histories $SUBREPO_HEAD

E fatto! In modo sicuro e senza alcuna magia.


... quale risposta è quella? Potrebbe voler fare riferimento al nome utente e la risposta migliore può cambiare nel tempo.
Contango,

Risposta @Contango aggiornata. ma la risposta migliore è ancora la risposta migliore con un vantaggio di 400 punti ;-)
dataless

Funziona se il sottorepo contiene già una directory chiamata subrepocon cose al suo interno?
detly

Nell'ultimo passaggio viene visualizzato il seguente errore: git merge $SUBREPO_HEAD fatal: refusing to merge unrelated historiesDevo utilizzare git merge $SUBREPO_HEAD --allow-unrelated-historiesin questo caso? O dovrebbe funzionare senza e ho fatto un errore?
Ti-m

1
@ Ti-m Sì, questo è esattamente il caso della fusione di due storie che non condividono alcun commit. La guardia contro storie non correlate sembra essere nuova da quando ho scritto per la prima volta; Aggiornerò la mia risposta.
dataless

3

Per quando

git rm [-r] --cached submodule_path

ritorna

fatal: pathspec 'emr/normalizers/' did not match any files

Contesto: l'ho fatto rm -r .git*nelle mie cartelle sottomodule prima di rendermi conto che dovevano essere de-sottomodificate nel progetto principale a cui le avevo appena aggiunte. Ho riscontrato l'errore sopra riportato durante la de-sottomodulazione di alcuni, ma non tutti. Ad ogni modo, li ho riparati eseguendo, (dopo, ovviamente, il rm -r .git*)

mv submodule_path submodule_path.temp
git add -A .
git commit -m "De-submodulization phase 1/2"
mv submodule_path.temp submodule_path
git add -A .
git commit -m "De-submodulization phase 2/2"

Si noti che ciò non preserva la storia.


3

Sulla base della risposta di VonC , ho creato un semplice script bash che lo fa. Alla addfine deve usare i caratteri jolly altrimenti annullerà il precedente rmper il sottomodulo stesso. È importante aggiungere il contenuto della directory del sottomodulo e non nominare la directory stessa nel addcomando.

In un file chiamato git-integrate-submodule:

#!/usr/bin/env bash
mv "$1" "${1}_"
git submodule deinit "$1"
git rm "$1"
mv "${1}_" "$1"
git add "$1/**"

0

Ho trovato più conveniente (anche?) Recuperare i dati di commit locali dal sottomodulo, perché altrimenti li perderei. (Impossibile spingerli perché non ho accesso a quel telecomando). Quindi ho aggiunto submodule / .git come remote_origin2, recuperato i commit e unito da quel ramo. Non sono sicuro se ho ancora bisogno del telecomando del sottomodulo come origine, dal momento che non ho ancora abbastanza familiarità con Git.


0

Ecco cosa ho trovato migliore e più semplice.

Nel repository sottomodulo, da HEAD si desidera unire il repository principale:

  • git checkout -b "mergeMe"
  • mkdir "foo/bar/myLib/" (percorso identico a quello in cui si desidera i file nel repository principale)
  • git mv * "foo/bar/myLib/" (sposta tutto nel percorso)
  • git commit -m "ready to merge into main"

Torna nel repository principale dopo aver rimosso il sottomodulo e aver cancellato il percorso "foo / bar / myLib":

  • git merge --allow-unrelated-histories SubmoduleOriginRemote/mergeMe

boom fatto

storie preservate

nessun problema


Nota questo quasi identico ad alcune altre risposte. Ma questo presuppone il tuo repository sottomodulo. Inoltre, è facile ottenere future modifiche a monte per il sottomodulo.

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.