2010-02-19 4 views
9

Je voudrais séparer des modules distribués avec une plus grande application en sous-modules séparés et garder la possibilité de tirer de l'amont.Utilisation répétée de git-filter-branch pour réécrire de nouveaux commits

C'est donc plus complexe que Detach subdirectory into separate Git repository. Je n'ai pas seulement besoin d'utiliser git-filter-branch une fois mais je veux garder la possibilité de tirer des changements en amont après que je l'ai fait (et pas en amont).

Il ne suffit pas de relancer git-filter-branch sur l'historique complet en amont, y compris les nouveaux commits que je n'ai pas trouvés dans mon historique réécrit car il y a des centaines de modules et le nombre de validations se rapprocher de 100.000. J'imagine que cela implique de limiter l'historique aux nouveaux commits, de les réécrire et de les ajouter après les commits précédemment réécrits, mais je ne sais pas comment faire cela - et peut-être qu'il y a une meilleure approche.

Ce serait bien si les branches et les étiquettes pouvaient être conservées, mais ce n'est pas absolument nécessaire et si cela complique les choses, je préférerais vraiment les perdre.

+0

Je voudrais aussi savoir à ce sujet. Chaque fois que je tire un dépôt de dépendance, je dois à nouveau exécuter filter-branche pour mettre les mises à jour dans mon projet (je ne veux pas fusionner le repo entier). –

+0

J'ai été surpris que personne ne trouve une réponse, après tout, il semble être un défi intéressant. Eh bien, j'ai piraté quelque chose ensemble mais j'ai oublié de le poster ici. Votre intérêt m'a rappelé - ci-dessous est ma solution. – tarsius

+2

Avez-vous déjà regardé [* git subtree *] (http://github.com/apenwarr/git-subtree/blob/master/git-subtree.txt)? Il peut diviser un sous-arbre en une nouvelle branche et, avec l'option '--rejoin', le faire de façon incrémentielle. –

Répondre

8

Pour la première rebasage faire ceci:

git checkout -b rebased master 
git filter-branch --some-filter 
git tag rebased-done master 

et "fusion" engage plus tard:

# Create a tempory branch and rebase it's tail use 'rebase-done~' 
# and not 'rebase-done' because some filters (like --index-filter) 
# require this, others might not. 
git checkout -b rebased-tail master 
git filter-branch -f --some-filter -- rebased-done~..HEAD 

# Get the commit in branch 'rebased' corresponding to tag 'rebase-done' 
# (which tags a commit in 'master' not 'rebased'). Depending on your 
# situation you might have to determine this commit differently (in my 
# use case I am absolutely sure that there is never a commit with the 
# same author date - if that doesn't work you might want to compare 
# commit messages). 
start_time=$(git show --quiet --pretty=%at rebased-done) 
start_hash=$(
git log --reverse --pretty="%H %at" rebased_tail | 
while read hash time 
do 
    [ "$time" = "$start_time" ] && echo $hash && break 
done 
) 

# Finally apply the rebased commits. 
git checkout rebased 
git format-patch -k --stdout $start_hash..rebased-tail | git am -k 
git branch -D rebased-tail 
git tag -f rebased-done master 
Questions connexes