séparer le dépôt git par sous-dossier et conserver toutes les anciennes branches
j'ai un git repo avec 2 répertoires et plusieurs branches, je veux les diviser et créer toutes les branches
`-- Big-repo
|-- dir1
`-- dir2
Branches : branch1, branch2, branch3 ...
Ce que je veux
je veux diviser dir1 et dir2 comme deux pensions séparées et conserver branches branch1, branch2 ... dans les deux référentiels.
dir1
Branches : branch1, branch2, branch3 ...
dir2
Branches : branch1, branch2, branch3 ...
Ce que j'ai essayé:
je suis capable de les diviser en 2 repos en utilisant
git subtree split -P dir1 -b dir1-only
git subtree split -P dir2 -b dir2-only
mais, il ne crée pas de branches après la séparation.
pour obtenir toutes les branches:
git checkout branch1 (in Big-repo)
git subtree split -p dir1 -b dir1-branch1
git checkout branch2 (in Big-repo)
git subtree split -p dir1 -b dir1-branch2
And push these branches to newly created repo.
cela implique plus d'effort manuel et je suis sûr qu'il pourrait y avoir un moyen rapide pour y parvenir?
des idées???
2 réponses
réponse Courte
git filter-branch
offre exactement la fonctionnalité que vous voulez. Avec l'option --subdirectory-filter
vous pouvez créer un nouvel ensemble de commits où le contenu de subDirectory
est à la racine du répertoire.
git filter-branch --prune-empty --subdirectory-filter subDirectory -- --branches
Walkthrough
ce qui suit est un exemple pour effectuer cette manière sûre. Vous devez effectuer cette opération pour chaque sous-répertoire qui sera isolé dans son propre repo, dans ce cas dir1
.
premier clone de votre dépôt pour isoler les changements:
git clone yourRemote dir1Clone
cd dir1Clone
Pour préparer la cloné référentiel, nous allons recréer toutes les branches locales. Nous sautons celui qui commence par *
puisque c'est la branche courante, qui dans ce cas se lirait (no branch)
puisque nous sommes dans un état sans tête:
# move to a headless state
# in order to delete all branches without issues
git checkout --detach
# delete all branches
git branch | grep --invert-match "*" | xargs git branch -D
pour recréer toutes les branches éloignées localement on passe en revue les résultats de git branch --remotes
. Nous sautons ceux qui contiennent ->
car ce ne sont pas des branches:
# get all local branches for remote
git branch --remotes --no-color | grep --invert-match "\->" | while read remote; do
git checkout --track "$remote"
done
# remove remote and remote branches
git remote remove origin
exécute finalement la commande filter-branch
. Cela créera de nouvelles propagations avec toutes les propagations qui touchent le sous-répertoire dir1
. Toutes les branches qui touchent aussi ce sous-répertoire seront mises à jour. La sortie listera toutes les références qui n'ont pas été mises à jour, ce qui est le cas pour les branches qui ne touchent pas du tout dir1
.
# Isolate dir1 and recreate branches
# --prune-empty removes all commits that do not modify dir1
# -- --all updates all existing references, which is all existing branches
git filter-branch --prune-empty --subdirectory-filter dir1 -- --all
Après cela, vous aurez une nouvelle série de commits qui ont dir1
à la racine du dépôt. Il suffit d'ajouter votre télécommande pour pousser les nouvelles propagations, ou de les utiliser comme un nouveau dépôt.
comme dernière étape supplémentaire si vous vous souciez de la taille du dépôt:
même si toutes les branches où votre dépôt a été mis à jour auront toujours tous les objets du dépôt original, ils ne seront accessibles qu'à travers la ref-journaux. Si vous voulez laisser tomber ceux-ci Lire comment collecter les ordures commits
Quelques ressources supplémentaires:
ce script fait le travail pour moi:
#!/bin/bash
set -e
if [ -z "" ]; then
echo "usage: "151900920" /full/path/to/repository path/to/splitfolder/from/repository/root new_origin"
exit
fi
repoDir=
folder=
newOrigin=
cd $repoDir
git checkout --detach
git branch | grep --invert-match "*" | xargs git branch -D
for remote in `git branch --remotes | grep --invert-match "\->"`
do
git checkout --track $remote
git add -vA *
git commit -vam "Changes from $remote" || true
done
git remote remove origin
git filter-branch --prune-empty --subdirectory-filter $folder -- --all
#prune old objects
rm -rf .git/refs/original/*
git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune
#upload to new remote
git remote add origin $newOrigin
git push origin master
for branch in `git branch | grep -v '\*'`
do
git push origin $branch
done