2016-10-10 1 views
0

Nous avons un grand dépôt qui a des sous-dossiers de platforms,Lancer git filtre-branche sous-répertoire-filtre également supprimer débarrasser d'autres sous-répertoires histoire

sdk/ 
    .git/ 
    android/ 
    ios/ 
    unity/ 
    windows/ 

Ce que nous voulons maintenant briser dans leurs propres dépôts. Garder toute l'histoire, et les branches de là.

J'ai couru la commande

git filter-branch -f --prune-empty --subdirectory-filter android -- --all 

Ce qui semblait avait couru exactement ce que j'avais voulu, promouvoir le sous-dossier android être la racine de ce nouveau dépôt, et je suis allé à pousser cette une nouvelle origine distante (sur GitHub).

Quand vous faites cela, je reçu un message d'erreur indiquant qu'il y avait un fichier trop volumineux pour être poussé à distance, mais le chemin de ce fichier était

unity/QAApp/... 

qui existe dans l'histoire des autres sous-dossiers que je ne pensait pas filter-branch --subdirectory-filter prendrait.

Je suis à la recherche dans l'exécution d'un manuel

git filter-branch -f --prune-empty --tree-filter \ 
'git rm -rf --ignore-unmatch ios unity windows && rm -rf ios unity windows' \ 
-- --all 

Mais il semble que ce double-agiotage ce que je comprends filter-branch subdirectory-filter devrait faire. Est-ce que ce comportement est attendu ou est-ce que j'exécute incorrectement l'une ou l'autre des commandes?

Répondre

0

Après un peu de retour et d'avance avec les gars de la liste de diffusion git, il semble que ce soit un problème avec filter-branch. Le problème principal ici est que la branche de filtre n'interagit qu'avec les branches qui ont interagi avec le sous-répertoire que vous spécifiez. Si vous avez des branches qui ne l'ont jamais fait, la commande ne s'en approchera pas, vous laissant dans votre repo un historique que vous ne voudrez peut-être pas.

La première façon d'obtenir ce que je veux est clair sur toutes les branches qui n'interagissent pas avec le sous-répertoire, dans ce cas android,

path=android/ 
git for-each-ref --format='%(refname)' | 
while read ref; do 
    if test "$(git rev-list --count "$ref" -- "$path")" = 0; then 
    echo "delete $ref" 
    fi 
done | git update-ref --stdin 

Cet extrait passe par toutes les branches de référence de votre git a, chèques pour voir si elle a une référence à votre sous-répertoire, et si ce n'est pas le cas, supprimez-le.

Changez ensuite la commande filtre-branche,

git filter-branch -f --prune-empty --tag-name-filter cat --subdirectory-filter android -- --all 

Ajout --tag-name-filter cat à la commande Refait les balises et arrête une branche étiquetée de garder la main de l'histoire non désirée.

La dernière chose à faire est ensuite sauvegardé essuyage maintenu l'histoire,

git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d 

La branche filtre stocke une sauvegarde de toutes les branches, il interagit avec. C'est un comportement correct et correct, mais à cette fin, lorsque vous voulez réécrire tout l'historique et comprendre les conséquences de ce que vous faites, alors supprimer la sauvegarde est correct et correct à faire. Après tout cela, vous obtenez un repo correctement refait, avec seulement l'historique de ce sous-répertoire, tout le reste est supprimé, y compris les branches qui n'ont jamais interagi avec ce sous-répertoire.