Détacher (déplacer) le sous-répertoire dans un dépôt git séparé
j'ai un dépôt Git qui contient un certain nombre de sous-répertoires. Maintenant, j'ai trouvé que l'un des sous-répertoires est pas lié à l'autre et doivent être détachés dans un autre référentiel.
Comment puis-je faire cela tout en gardant l'historique des fichiers dans le sous-répertoire?
je suppose que je pourrais faire un clone et enlever les parties indésirables de chaque clone, mais je suppose que cela me donnerait l'arbre complet quand vérifier une révision plus ancienne, etc. Cela pourrait être acceptable, mais je préférerais pouvoir prétendre que les deux dépôts n'ont pas une histoire commune.
juste pour être clair, j'ai la structure suivante:
XYZ/
.git/
XY1/
ABC/
XY2/
mais je voudrais plutôt ceci:
XYZ/
.git/
XY1/
XY2/
ABC/
.git/
ABC/
22 réponses
Update : ce processus est si courant, que l'équipe git l'a simplifié avec un nouvel outil, git subtree
. Voir ici: Détacher (se déplacer) sous-répertoire en séparer dépôt Git
Vous voulez cloner votre dépôt et ensuite utiliser git filter-branch
pour marquer tout, mais le sous-répertoire que vous voulez dans votre nouveau repo être récupérées.
-
pour cloner votre dépôt local:
git clone /XYZ /ABC
(Note: le dépôt sera cloné à l'aide de liens durs, mais ce n'est pas un problème puisque les fichiers reliés ne seront pas modifiés en eux-mêmes-de nouveaux seront créés.)
-
maintenant, préservons les branches intéressantes que nous voulons réécrire aussi bien, et puis enlever l'origine pour éviter d'y pousser et pour s'assurer que les vieilles commits ne seront pas référencé par l'origine:
cd /ABC for i in branch1 br2 br3; do git branch -t $i origin/$i; done git remote rm origin
ou pour toutes les branches éloignées:
cd /ABC for i in $(git branch -r | sed "s/.*origin\///"); do git branch -t $i origin/$i; done git remote rm origin
-
Maintenant, vous pourriez vouloir également supprimer les étiquettes qui n'ont pas de relation avec le sous-projet; vous pouvez également le faire plus tard, mais vous pourriez avoir besoin de tailler votre repo à nouveau. Je ne l'ai pas fait et j'ai obtenu un
WARNING: Ref 'refs/tags/v0.1' is unchanged
pour toutes les étiquettes (puisqu'elles étaient toutes sans rapport avec le sous-projet); en outre, après avoir enlevé ces étiquettes plus d'espace sera récupéré. Apparemmentgit filter-branch
devrait être capable de réécrire d'autres tags, mais je n'ai pas pu le vérifier. Si vous voulez supprimer toutes les étiquettes, utilisezgit tag -l | xargs git tag -d
. -
ensuite, utilisez la branche de filtre et réinitialiser pour exclure les autres fichiers, afin qu'ils puissent être élagués. Ajoutons aussi
--tag-name-filter cat --prune-empty
pour supprimer les propagations vides et réécrire les tags (notez que cela devra supprimer leur signature):git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC -- --all
ou bien, pour réécrire uniquement la tête branche et ignorer tags et autres branches:
git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter ABC HEAD
-
puis supprimer les réflogs de sauvegarde afin que l'espace puisse être vraiment récupéré (bien que maintenant l'opération soit destructive)
git reset --hard git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d git reflog expire --expire=now --all git gc --aggressive --prune=now
et maintenant vous avez un dépôt Git local du sous-répertoire ABC avec toute son histoire préservée.
Note: pour la plupart des utilisations, git filter-branch
devrait en effet avoir le paramètre ajouté -- --all
. Oui, c'est vraiment - - l'espace - - all
. Ceci doit être le dernier paramètre de la commande. Comme Matli l'a découvert, cela maintient les branches de projet et les tags inclus dans le nouveau repo.
éditer: diverses suggestions des commentaires ci-dessous ont été incorporés pour s'assurer, par exemple, que le dépôt est effectivement réduction (ce qui n'était pas toujours le cas avant).
La Voie De La Facilité™
il s'avère que c'est une pratique si commune et utile que les overlords de git l'ont rendue vraiment facile, mais vous devez avoir une nouvelle version de git (>= 1.7.11 mai 2012). Voir le annexe pour savoir comment installer le dernier git. Aussi, il y a un exemple du monde réel dans le walkthrough ci-dessous.
-
préparer la old repo
pushd <big-repo> git subtree split -P <name-of-folder> -b <name-of-new-branch> popd
Note:
<name-of-folder>
ne doit pas contenir de caractères principaux ou secondaires. Par exemple, le dossier nommésubproject
doit être passé commesubproject
, pas./subproject/
Note pour les utilisateurs de windows: lorsque la profondeur de votre dossier est > 1,
<name-of-folder>
doit avoir un séparateur de dossier de style nix (/). Par exemple, le dossier nommépath1\path2\subproject
doit être passé commepath1/path2/subproject
-
Créer le nouveau repo
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
-
reliez le nouveau repo à Github ou n'importe où
git remote add origin <git@github.com:my-user/new-repo.git> git push origin -u master
-
Nettoyage", si désiré
popd # get out of <new-repo> pushd <big-repo> git rm -rf <name-of-folder>
Note : cela laisse toutes les références historiques dans le dépôt.Voir appendice ci-dessous si vous êtes en fait préoccupé d'avoir commis un mot de passe ou vous avez besoin de diminuer la taille du fichier de votre dossier
.git
.
...
Walkthrough
ce sont les mêmes étapes que ci-dessus , mais en suivant mes étapes exactes pour mon dépôt au lieu d'utiliser <meta-named-things>
.
voici un projet que j'ai pour implémenter JavaScript browser modules dans le noeud:
tree ~/Code/node-browser-compat
node-browser-compat
├── ArrayBuffer
├── Audio
├── Blob
├── FormData
├── atob
├── btoa
├── location
└── navigator
je veux séparer un seul dossier, btoa
, en un dépôt git séparé
pushd ~/Code/node-browser-compat/
git subtree split -P btoa -b btoa-only
popd
j'ai maintenant une nouvelle branche, btoa-only
, qui n'a que des commits pour btoa
et je veux créer un nouveau dépôt.
mkdir ~/Code/btoa/
pushd ~/Code/btoa/
git init
git pull ~/Code/node-browser-compat btoa-only
ensuite je crée un nouveau repo sur GitHub ou bitbucket, ou quoi que ce soit, et je l'ajoute c'est le origin
(btw, "origin" est juste une convention, pas une partie de la commande - vous pouvez l'appeler "remote-server" ou ce que vous voulez)
git remote add origin git@github.com:node-browser-compat/btoa.git
git push origin -u master
bonne journée!
Note: si vous avez créé une pension avec un README.md
, .gitignore
et LICENSE
, vous devrez tirer en premier:
git pull origin -u master
git push origin -u master
enfin, je vais vouloir supprimer le dossier de la plus grande pension
git rm -rf btoa
...
appendice
dernière version sur OS X
pour obtenir la dernière version de git:
brew install git
pour obtenir brew pour OS X:
dernière version sur Ubuntu
sudo apt-get update
sudo apt-get install git
git --version
si cela ne fonctionne pas (vous avez une très ancienne version d'ubuntu), essayez
sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git
si ça ne marche toujours pas, essayez
sudo chmod +x /usr/share/doc/git/contrib/subtree/git-subtree.sh
sudo ln -s \
/usr/share/doc/git/contrib/subtree/git-subtree.sh \
/usr/lib/git-core/git-subtree
grâce à rui.araujo des commentaires.
effacer votre histoire
par défaut Supprimer des fichiers de git ne les supprime pas réellement de git, il s'engage simplement qu'ils ne sont plus là. Si vous voulez réellement supprimer les références historiques (i.e. vous avez un mot de passe engagé), vous devez le faire:
git filter-branch --prune-empty --tree-filter 'rm -rf <name-of-folder>' HEAD
Après cela, vous pouvez vérifier que votre fichier ou folder n'apparaît plus du tout dans l'historique git
git log -- <name-of-folder> # should show nothing
Cependant, vous ne peut pas "pousser" les suppressions de github et ainsi de suite. Si vous essayez, vous obtiendrez une erreur et vous devrez git pull
avant de pouvoir git push
- et alors vous êtes de retour à avoir tout dans votre histoire.
donc si vous voulez supprimer l'histoire de la "Origine" - ce qui signifie de le supprimer de GitHub, bitbucket, etc - vous aurez besoin de supprimer le repo et re-pousser un taillés copie du repo. Mais attendez - il y a plus ! - Si vous êtes vraiment soucieux de se débarrasser d'un mot de passe ou quelque chose comme ça, vous aurez besoin de tailler la sauvegarde (voir ci-dessous).
faire .git
petits
la commande delete history mentionnée ci - dessus laisse encore un tas de fichiers de sauvegarde-parce que git est trop aimable pour vous aider à ne pas ruiner votre repo par accident. Il éventuellement supprimé les fichiers orphelins au cours des jours et des mois, mais il les laisse là pendant un certain temps au cas où vous réalisez que vous accidentellement supprimé quelque chose que vous ne vouliez pas.
donc si vous voulez vraiment vider la poubelle à réduire la taille du clone d'une pension immédiatement vous devez faire tout ce truc vraiment bizarre:
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune=now
git reflog expire --all --expire-unreachable=0
git repack -A -d
git prune
cela dit, je recommande de ne pas effectuer ces étapes sauf si tu sais que tu dois ... juste au cas où tu as taillé le mauvais sous - répertoire, tu sais? Les fichiers de sauvegarde ne devraient pas être clonés quand vous appuyez sur la mise en veille, ils seront juste dans votre copie locale.
crédit
Paul's answer crée un nouveau dépôt contenant /ABC, mais ne supprime pas /ABC de l'intérieur /XYZ. La commande suivante supprimera / ABC de / XYZ:
git filter-branch --tree-filter "rm -rf ABC" --prune-empty HEAD
bien sûr, testez-le dans un dépôt 'clone --no-hardlinks' en premier, et suivez-le avec les commandes reset, gc et prune Paul listes.
j'ai trouvé que pour correctement supprimer l'ancienne histoire du nouveau dépôt, vous devez faire un peu plus de travail après l'étape filter-branch
.
-
Faire le clone et le filtre:
git clone --no-hardlinks foo bar; cd bar git filter-branch --subdirectory-filter subdir/you/want
-
Supprimer toute référence à l'histoire ancienne. "origin" gardait la trace de votre clone, et "original" est où filter-branch sauve les vieux trucs:
git remote rm origin git update-ref -d refs/original/refs/heads/master git reflog expire --expire=now --all
-
même maintenant, votre histoire pourrait être coincée dans un fichier que fsck ne touchera pas. Déchirez - le en lambeaux, en créant un nouveau fichier pack et en supprimant les objets inutilisés:
git repack -ad
Il y a , une explication de ce dans le manuel pour filter-branch .
Edit: script Bash ajouté.
les réponses données ici n'ont fonctionné que partiellement pour moi; beaucoup de gros fichiers sont restés dans le cache. Ce qui a finalement fonctionné (après les heures dans #git sur freenode):
git clone --no-hardlinks file:///SOURCE /tmp/blubb
cd blubb
git filter-branch --subdirectory-filter ./PATH_TO_EXTRACT --prune-empty --tag-name-filter cat -- --all
git clone file:///tmp/blubb/ /tmp/blooh
cd /tmp/blooh
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now
avec les solutions précédentes, la taille du dépôt était d'environ 100 MB. Celui-ci l'a ramené à 1,7 mo. Peut-être que ça aide quelqu'un :)
Le script bash suivant automatise la tâche:
!/bin/bash
if (( $# < 3 ))
then
echo "Usage: "151910920" </path/to/repo/> <directory/to/extract/> <newName>"
echo
echo "Example: "151910920" /Projects/42.git first/answer/ firstAnswer"
exit 1
fi
clone=/tmp/Clone
newN=/tmp/
git clone --no-hardlinks file:// ${clone}
cd ${clone}
git filter-branch --subdirectory-filter --prune-empty --tag-name-filter cat -- --all
git clone file://${clone} ${newN}
cd ${newN}
git reflog expire --expire=now --all
git repack -ad
git gc --prune=now
ce n'est plus aussi complexe vous pouvez simplement utiliser la commande git filter-branch sur un clone de vous repo pour sélectionner les sous-répertoires que vous ne voulez pas et puis pousser sur la nouvelle télécommande.
git filter-branch --prune-empty --subdirectory-filter <YOUR_SUBDIR_TO_KEEP> master
git push <MY_NEW_REMOTE_URL> -f .
Update : le module git-subtree était tellement utile que l'équipe git l'a tiré dans le noyau et l'a fait git subtree
. Voir ici: Détacher (se déplacer) sous-répertoire en séparer dépôt Git
git-sous-arborescence peut être utile pour cette
http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt (déprécié)
http://psionides.jogger.pl/2010/02/04/sharing-code-between-projects-with-git-subtree /
Voici une petite modification de CoolAJ86 's "the Easy Way™" answer afin de scinder multiple folders sub (disons sub1
et sub2
) en un nouveau dépôt git.
la Voie de La facilité™ (plusieurs sous-dossiers)
-
Préparer le vieux repo
pushd <big-repo> git filter-branch --tree-filter "mkdir <name-of-folder>; mv <sub1> <sub2> <name-of-folder>/" HEAD git subtree split -P <name-of-folder> -b <name-of-new-branch> popd
Note:
<name-of-folder>
ne doit pas contenir de caractères principaux ou secondaires. Par exemple, le dossier nommésubproject
doit être passé commesubproject
, pas./subproject/
Note pour les utilisateurs de windows: lorsque la profondeur de votre dossier est > 1,
<name-of-folder>
doit avoir un séparateur de dossier *nix style (/). Par exemple, le dossier nommépath1\path2\subproject
doit être passé commepath1/path2/subproject
. De plus, n'utilisez pas la commandemv
maismove
.note finale: la différence unique et grande avec la réponse de base est la deuxième ligne du script "
git filter-branch...
" -
Créer le nouveau repo
mkdir <new-repo> pushd <new-repo> git init git pull </path/to/big-repo> <name-of-new-branch>
-
reliez le nouveau repo à Github ou n'importe où
git remote add origin <git@github.com:my-user/new-repo.git> git push origin -u master
-
Nettoyage", si désiré
popd # get out of <new-repo> pushd <big-repo> git rm -rf <name-of-folder>
Note : il reste toutes les références historiques dans le dépôt.Voir le annexe dans la réponse originale si vous êtes réellement préoccupé d'avoir commis un mot de passe ou si vous avez besoin de diminuer la taille du fichier de votre dossier
.git
.
la question initiale veut que XYZ/ABC/(*files) devienne ABC/ABC/(*files). Après avoir implémenté la réponse acceptée pour mon propre code, j'ai remarqué qu'elle change en fait XYZ/ABC/(*files) en ABC/(*files). La page de manuel filter-branch dit même,
le résultat contiendra ce répertoire (et seulement cela) comme sa racine de projet ."
En d'autres termes, il favorise le dossier de niveau supérieur "" niveau. C'est une distinction importante parce que, par exemple, dans mon histoire, j'avais renommé un dossier de niveau supérieur. En faisant la promotion de dossiers "up" un niveau, git perd la continuité à la propagation où j'ai fait le renommage.
ma réponse à la question est alors de faire 2 copies du dépôt et supprimer manuellement le(S) dossier (s) que vous voulez garder dans chacun. La page de manuel me soutient avec ceci:
[...] évitez d'utiliser [cette commande] si une simple commit suffit à résoudre votre problème
pour ajouter à la réponse de Paul , j'ai trouvé que pour finalement récupérer de l'espace, je dois pousser la tête à un dépôt propre et qui diminue la taille de la .git/objects/pack répertoire.
c'est à dire
$ mkdir ...ABC.git $ cd ...ABC.git $ git init --bare
après le gc prune, faites aussi:
$ git push ...ABC.git HEAD
, Alors vous pouvez faire
$ git clone ...ABC.git
et la taille de ABC/.réduction de git 151970920"
en fait, certains de les étapes chronophages (par ex. git gc) ne sont pas nécessaires avec la pression pour nettoyer le dépôt, i.e.:
$ git clone --no-hardlinks /XYZ /ABC $ git filter-branch --subdirectory-filter ABC HEAD $ git reset --hard $ git push ...ABC.git HEAD
la bonne voie est maintenant la suivante:
git filter-branch --prune-empty --subdirectory-filter FOLDER_NAME [first_branch] [another_branch]
GitHub ont maintenant même petit article sur de tels cas.
mais assurez-vous de cloner votre repo d'origine pour séparer le répertoire en premier (comme il supprimerait tous les fichiers et les autres répertoires et vous avez probablement besoin de travailler avec eux).
donc votre algorithme devrait être:
- clonez votre distance repo à un autre répertoire
- utilisant
git filter-branch
n'a laissé que des fichiers sous un sous-répertoire, push à New remote - créer engageons à supprimer ce sous-répertoire de votre télécommande d'origine repo
Il semble que la plupart (toutes?) des réponses ici s'appuient sur une certaine forme de git filter-branch --subdirectory-filter
et de ses semblables. Cela peut fonctionner "la plupart du temps" Cependant pour certains cas, par exemple le cas de quand vous avez renommé le dossier, ex:
ABC/
/move_this_dir # did some work here, then renamed it to
ABC/
/move_this_dir_renamed
si vous faites un style de filtre git normal pour extraire" move_me_renamed "vous perdrez l'historique de changement de fichier qui s'est produit de dos quand il a été initialement move_this_dir ( ref ).
il ainsi il semble que la seule façon de vraiment garder tout l'histoire de changement (si la vôtre est un cas comme celui-ci), est, en essence, de copier le dépôt (créer un nouveau repo, définir que d'être l'origine), puis tout le reste nuke et renommer le sous-répertoire au parent comme ceci:
- cloner le projet multi-modules localement
- Branches-vérifier ce qui est là:
git branch -a
- faire une caisse à chaque branche à inclure dans le fractionnement pour obtenir une copie locale sur votre poste de travail:
git checkout --track origin/branchABC
- Faire une copie dans un nouveau répertoire:
cp -r oldmultimod simple
- allez dans la nouvelle copie du projet:
cd simple
- se débarrasser des autres modules qui ne sont pas nécessaires dans ce projet:
-
git rm otherModule1 other2 other3
- Maintenant seul le sous-DIR du module cible reste
- se débarrasser du module subdiviser de sorte que la racine du module devienne la nouvelle racine du projet
-
git mv moduleSubdir1/* .
- supprimer la relique:
rmdir moduleSubdir1
- vérifier les changements en tout point:
git status
- créer la nouvelle git repo et copier son URL pour pointer ce projet en elle:
-
git remote set-url origin http://mygithost:8080/git/our-splitted-module-repo
- vérifier que c'est bien:
git remote -v
- Pousser les modifications jusqu'à la distance repo:
git push
- allez au rapport à distance et vérifiez que tout est là
- répéter pour toute autre branche nécessaire:
git checkout branch2
Ce qui suit le github doc "Fractionnement d'un sous-dossier dans un nouveau référentiel" les étapes 6 à 11 pour pousser le module à un nouveau repo.
cela ne vous épargnera pas de place dans votre .dossier git, mais il préservera tous vos changez l'historique pour ces fichiers, même à travers les renommages. Et cela peut ne pas valoir la peine s'il n'y a pas "beaucoup" d'histoire perdue, etc. Mais au moins vous êtes garanti de ne pas perdre plus vieux commits!
j'ai eu exactement ce problème mais toutes les solutions standard basées sur git filter-branch étaient extrêmement lentes. Si vous avez un petit référentiel alors c'est peut-être pas un problème, c'était pour moi. J'ai écrit un autre programme de filtrage git basé sur libgit2 qui, dans un premier temps, crée des branches pour chaque filtrage du dépôt primaire et les pousse ensuite à nettoyer les dépôts comme étape suivante. Sur mon dépôt (500MB 100000 commits) les méthodes standard git filter-branch ont pris des jours. Mon le programme prend des minutes pour faire le même filtrage.
il a le nom fabuleux de git_filter et vit ici:
https://github.com/slobobaby/git_filter
sur GitHub.
j'espère qu'il est utile à quelqu'un.
pour ce que ça vaut, voici comment utiliser GitHub sur une machine Windows. Disons que vous avez un rapport cloné dans C:\dir1
. La structure du répertoire ressemble à ceci: C:\dir1\dir2\dir3
. Le dir3
répertoire est celui que je veux être un nouveau repo.
Github:
- créez votre nouveau dépôt:
MyTeam/mynewrepo
Invite Bash:
-
$ cd c:/Dir1
-
$ git filter-branch --prune-empty --subdirectory-filter dir2/dir3 HEAD
Retourné:Ref 'refs/heads/master' was rewritten
(pour information: dir2/dir3 est sensible à la casse.) -
$ git remote add some_name git@github.com:MyTeam/mynewrepo.git
git remote add origin etc
. n'a pas fonctionné, retourné "remote origin already exists
" -
$ git push --progress some_name master
Comme je l' mentionné ci-dessus , j'ai dû utiliser l'inverse de la solution (suppression de tous les s'engage à ne pas toucher à mon dir/subdir/targetdir
) qui semblait fonctionner assez bien en retrait d'environ 95% de la commet (comme souhaité). Il reste toutefois deux petites questions à régler.
PREMIÈRE , filter-branch
a fait un bang à l'emploi de retrait qui s'engage introduire ou de modifier le code, mais apparemment, fusion s'engage sont au-dessous de sa gare dans le Gitiverse.
C'est un problème esthétique que je peux probablement vivre avec (dit-il...la sauvegarde doucement avec les yeux évitée) .
DEUXIÈME les quelques commits qui restent sont assez bien TOUS dupliqués! Il semble que j'ai acquis une deuxièmement, un calendrier redondant qui couvre à peu près toute l'histoire du projet. La chose intéressante (que vous pouvez voir sur la photo ci-dessous), est que mes trois branches locales ne sont pas toutes sur la même ligne de temps (ce qui est, certainement pourquoi il existe et n'est pas seulement des ordures collectées).
La seule chose que je peux imaginons que l'un des commits supprimés était, peut-être, la seule commit de fusion que filter-branch
effectivement supprimé , et qui a créé la ligne de temps parallèle que chaque maintenant-toron non fusionné a pris sa propre copie des commits. ( shrug Où est mon TARDiS?) Je suis assez sûr que je peux résoudre ce problème, bien que je vraiment j'aimerais comprendre comment c'est arrivé.
dans le cas de crazy mergefest-O-RAMA, je vais probablement en laissant celui-ci seul puisqu'il s'est si fermement enraciné dans mon histoire de commit-menaçant à moi chaque fois que je m'approche -, il ne semble pas être en train de causer des problèmes non-cosmétiques et parce qu'il est assez joli dans la Tour.App.
utilisez cette commande filter pour supprimer un sous-répertoire, tout en préservant vos tags et branches:
git filter-branch --index-filter \
"git rm -r -f --cached --ignore-unmatch DIR" --prune-empty \
--tag-name-filter cat -- --all
La Façon La Plus Facile
- installer
git splits
. Je l'ai créé comme une extension git, basé sur solution de jkeating . -
#change into your repo's directory cd /path/to/repo #checkout the branch git checkout XYZ
#split multiple directories into new branch XYZ git splits -b XYZ XY1 XY2 -
créer un repo vide quelque part. Nous supposerons que nous avons créé un repo vide appelé
xyz
sur GitHub qui a le chemin:git@github.com:simpliwp/xyz.git
-
Pousser vers le nouveau repo.
#add a new remote origin for the empty repo so we can push to the empty repo on GitHub git remote add origin_xyz git@github.com:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master
-
cloner la nouvelle mise à distance repo dans un nouveau répertoire local
#change current directory out of the old repo cd /path/to/where/you/want/the/new/local/repo #clone the remote repo you just pushed to git clone git@github.com:simpliwp/xyz.git
vous pourriez avoir besoin de quelque chose comme" git reflog expire --expire=now --all " avant la collecte des ordures pour réellement nettoyer les fichiers. git filter-branch ne supprime que les références dans l'historique, mais ne supprime pas les entrées qui contiennent les données. Bien sûr, le test de cette première.
mon utilisation de disque a chuté de façon spectaculaire en faisant ceci, bien que mes conditions initiales aient été quelque peu différentes. Peut-être sous-répertoire-filtre nie ce besoin, mais j'en doute.
Check out git_split project à https://github.com/vangorra/git_split
transforment les répertoires git en leurs propres dépôts dans leur propre emplacement. Pas de sous-arbre drôle d'affaires. Ce script prendra un répertoire existant dans votre dépôt git et le transformera en un dépôt indépendant. En cours de route, il copiera tout l'historique des modifications pour le répertoire que vous avez fourni.
./git_split.sh <src_repo> <src_branch> <relative_dir_path> <dest_repo>
src_repo - The source repo to pull from.
src_branch - The branch of the source repo to pull from. (usually master)
relative_dir_path - Relative path of the directory in the source repo to split.
dest_repo - The repo to push to.
mettez ceci dans votre gitconfig:
reduce-to-subfolder = !sh -c 'git filter-branch --tag-name-filter cat --prune-empty --subdirectory-filter cookbooks/unicorn HEAD && git reset --hard && git for-each-ref refs/original/ | cut -f 2 | xargs -n 1 git update-ref -d && git reflog expire --expire=now --all && git gc --aggressive --prune=now && git remote rm origin'
je suis sûr que git subtree est tout bon et merveilleux, mais mes sous-répertoires de Git code géré que je voulais déplacer était tout dans eclipse. Donc si vous utilisez egit, c'est douloureusement facile. Prendre le projet que vous souhaitez déplacer et de l'équipe->débrancher, puis de l'équipe->action vers le nouvel emplacement. Il sera par défaut d'essayer d'utiliser l'ancien emplacement repo, mais vous pouvez décocher la sélection use-existing et choisir le nouvel endroit pour le déplacer. Je salue tout egit.
je recommande de GitHub guide de fractionnement des sous-dossiers dans un nouveau dépôt . Les étapes sont similaires à la réponse de Paul , mais j'ai trouvé leurs instructions plus faciles à comprendre.
j'ai modifié les instructions pour qu'elles s'appliquent à un dépôt local, plutôt qu'à un dépôt hébergé sur GitHub.
fractionnement d'un sous-dossier en un nouveau dépôt
Ouvrir Git Bash.
changez le répertoire de travail courant à l'endroit où vous voulez créer votre nouveau dépôt.
cloner le dépôt contenant le sous-dossier.
git clone OLD-REPOSITORY-FOLDER NEW-REPOSITORY-FOLDER
- modifier la répertoire de travail courant de votre dépôt cloné.
cd REPOSITORY-NAME
- pour filtrer le sous-dossier du reste des fichiers du dépôt, Lancez
git filter-branch
, en fournissant cette information:
FOLDER-NAME
: le dossier de votre projet dans lequel vous souhaitez créer un dépôt séparé.
- Conseil: les utilisateurs de Windows doivent utiliser
/
pour délimiter les dossiers.BRANCH-NAME
: la branche par défaut pour votre projet actuel, par exemple,master
ough-pages
.
git filter-branch --prune-empty --subdirectory-filter FOLDER-NAME BRANCH-NAME # Filter the specified branch in your directory and remove empty commits Rewrite 48dc599c80e20527ed902928085e7861e6b3cbe6 (89/89) Ref 'refs/heads/BRANCH-NAME' was rewritten