Cette question est basée sur le sous-répertoire Detach dans un référentiel Git séparé
Au lieu de détacher un seul sous-répertoire, je veux en détacher un couple. Par exemple, mon arborescence de répertoires actuelle ressemble à ceci:
/apps
/AAA
/BBB
/CCC
/libs
/XXX
/YYY
/ZZZ
Et j'aimerais plutôt ceci:
/apps
/AAA
/libs
/XXX
L' --subdirectory-filter
argument to git filter-branch
ne fonctionnera pas car il supprime tout sauf le répertoire donné la première fois qu'il est exécuté. Je pensais que l'utilisation de l' --index-filter
argument pour tous les fichiers indésirables fonctionnerait (bien que fastidieux), mais si j'essaie de l'exécuter plus d'une fois, j'obtiens le message suivant:
Cannot create a new backup.
A previous backup already exists in refs/original/
Force overwriting the backup with -f
Des idées? TIA
la source
--tag-name-filter cat
à vos paramètresÉtapes manuelles avec de simples commandes git
Le plan est de diviser les répertoires individuels en ses propres dépôts, puis de les fusionner. Les étapes manuelles suivantes n'utilisaient pas de scripts de geek mais des commandes faciles à comprendre et pourraient aider à fusionner N sous-dossiers supplémentaires dans un autre référentiel unique.
Diviser
Supposons que votre dépôt d'origine est: original_repo
1 - Applications fractionnées:
2 - Diviser les bibliothèques
Continuez si vous avez plus de 2 dossiers. Vous allez maintenant avoir deux nouveaux référentiels git temporaires.
Conquérir en fusionnant des applications et des bibliothèques
3 - Préparez le tout nouveau repo:
Et vous devrez faire au moins un commit. Si les trois lignes suivantes doivent être ignorées, votre premier dépôt apparaîtra immédiatement sous la racine de votre dépôt:
Avec le fichier temporaire validé, la
merge
commande dans la section suivante s'arrêtera comme prévu.En vous basant sur les commentaires des utilisateurs, au lieu d'ajouter un fichier aléatoire comme
a_file_and_make_a_commit
, vous pouvez choisir d'ajouter un.gitignore
, ouREADME.md
etc.4 - Fusionner d'abord le repo des applications:
Vous devriez maintenant voir le répertoire des applications dans votre nouveau référentiel.
git log
devrait afficher tous les messages de validation historiques pertinents.Remarque: comme Chris l'a noté ci-dessous dans les commentaires, pour la version plus récente (> = 2.9) de git, vous devez spécifier
--allow-unrelated-histories
avecgit merge
5 - Fusionnez ensuite libs repo de la même manière:
Continuez si vous avez plus de 2 dépôts à fusionner.
Référence: Fusionner un sous-répertoire d'un autre référentiel avec git
la source
.gitignore
etREADME.md
fichiers.git merge .. git read-tree
étape, car elle les enregistre comme des fichiers nouvellement ajoutés et tous mes git guis ne font pas la connexion à leurs commits précédents.Pourquoi voudriez-vous courir
filter-branch
plus d'une fois? Vous pouvez tout faire en un seul balayage, donc pas besoin de le forcer (notez que vous devezextglob
activer dans votre shell pour que cela fonctionne):Cela devrait éliminer tous les changements dans les sous-répertoires indésirables et conserver toutes vos branches et commits (à moins qu'ils n'affectent uniquement les fichiers dans les sous-répertoires élagués, en vertu de
--prune-empty
) - aucun problème avec les commits en double, etc.Après cette opération, les répertoires indésirables seront répertoriés comme non suivis par
git status
.Le
$(ls ...)
st nécessaireextglob
est évalué par votre shell au lieu du filtre d'index, qui utilise lesh
builtineval
(oùextglob
n'est pas disponible). Voir Comment activer les options du shell dans git? pour plus de détails à ce sujet.la source
git
commandes, et n'est donc pas aussi sensible aux différences d'ls
interprétation de l 'entre les systèmes d'exploitation, comme l'a découvert @Bae.Répondre à ma propre question ici ... après de nombreux essais et erreurs.
J'ai réussi à le faire en utilisant une combinaison de
git subtree
etgit-stitch-repo
. Ces instructions sont basées sur:Tout d'abord, j'ai sorti les répertoires que je voulais conserver dans leur propre référentiel séparé:
J'ai ensuite créé un nouveau référentiel vide et y ai importé / assemblé les deux derniers:
Cela crée deux branches
master-A
etmaster-B
, chacune contenant le contenu de l'un des dépôts cousus. Pour les combiner et nettoyer:Maintenant, je ne sais pas trop comment / quand cela se produit, mais après le premier
checkout
et lepull
, le code fusionne comme par magie dans la branche master (toute idée de ce qui se passe ici est appréciée!)Tout semble avoir fonctionné comme prévu, sauf que si je regarde l'
newRepo
historique des commit, il y a des doublons lorsque le changeset a affecté à la foisapps/AAA
etlibs/XXX
. S'il existe un moyen de supprimer les doublons, ce serait parfait.la source
export PERL5LIB="$PERL5LIB:/usr/local/git/lib/perl5/site_perl/"
à ma configuration bash pour qu'elle puisse trouver Git.pm. Ensuite, je l'ai installé avec cpan.git subtree add
pour effectuer cette tâche. Voir stackoverflow.com/a/58253979/1894803J'ai écrit un filtre git pour résoudre exactement ce problème. Il porte le nom fantastique de git_filter et se trouve sur github ici:
https://github.com/slobobaby/git_filter
Il est basé sur l'excellent libgit2.
J'avais besoin de diviser un grand référentiel avec de nombreux commits (~ 100000) et les solutions basées sur git filter-branch ont pris plusieurs jours à s'exécuter. git_filter prend une minute pour faire la même chose.
la source
Utiliser l'extension git 'git splits'
git splits
est un script bash qui est un wrapper autourgit branch-filter
que j'ai créé en tant qu'extension git, basé sur la solution de jkeating .Il a été fait exactement pour cette situation. Pour votre erreur, essayez d'utiliser l'
git splits -f
option pour forcer la suppression de la sauvegarde. Comme ilgit splits
fonctionne sur une nouvelle branche, il ne réécrira pas votre branche actuelle, donc la sauvegarde est superflue. Voir le readme pour plus de détails et assurez-vous de l'utiliser sur une copie / clone de votre dépôt (juste au cas où!) .git splits
.Divisez les répertoires en une branche locale
#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 apps/AAA libs/ZZZ
Créez un dépôt vide quelque part. Nous supposerons que nous avons créé un dépôt vide appelé
xyz
sur GitHub qui a le chemin:[email protected]:simpliwp/xyz.git
Poussez 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 [email protected]:simpliwp/xyz.git #push the branch to the empty repo's master branch git push origin_xyz XYZ:master
Cloner le référentiel distant nouvellement créé 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 [email protected]:simpliwp/xyz.git
la source
la source
for
boucle vaut la peine d'être reconnue, car d'autres réponses similaires ne l'incluent pas. Si vous ne disposez pas d'une copie locale de chaque branche dans votre clone, vous ne les comptez pasfilter-branch
dans le cadre de sa réécriture, ce qui pourrait potentiellement exclure les fichiers introduits dans d'autres branches, mais pas encore fusionnés avec votre branche actuelle. (Bien que cela vaut également la peine de faire ungit fetch
sur toutes les branches que vous avez déjà vérifiées pour vous assurer qu'elles restent à jour.)Une solution simple: git-filter-repo
J'ai eu un problème similaire et, après avoir examiné les différentes approches répertoriées ici, j'ai découvert git-filter-repo . Il est recommandé comme alternative à git-filter-branch dans la documentation officielle de git ici .
Pour créer un nouveau référentiel à partir d'un sous-ensemble de répertoires dans un référentiel existant, vous pouvez utiliser la commande:
Filtrez plusieurs fichiers / dossiers en les chaînant:
Donc, pour répondre à la question d'origine , avec git-filter-repo, vous auriez juste besoin de la commande suivante:
la source
Ouais. Forcer le remplacement de la sauvegarde en utilisant l'
-f
indicateur sur les appels suivants àfilter-branch
pour remplacer cet avertissement. :) Sinon, je pense que vous avez la solution (c'est-à-dire éradiquer un répertoire indésirable à la fois avecfilter-branch
).la source
Supprimez la sauvegarde présente sous le répertoire .git dans refs / original comme le suggère le message. Le répertoire est masqué.
la source