J'ai expérimenté l'utilisation de git subtree et j'ai rencontré la situation suivante.
J'ai utilisé git subtree pour ajouter un projet externe à mon référentiel, j'ai intentionnellement gardé toute l'histoire du projet en amont car je veux pouvoir me référer à l'historique du projet et aussi contribuer au projet en amont plus tard.
En fait, un autre contributeur au projet en amont a accidentellement poussé un gros fichier dans la branche principale. Pour résoudre ce problème, le projet en amont a réécrit l'histoire et la force a poussé sur le maître. Lors de la création de mon "monorepo", j'ai inclus ce commit et je voudrais également le supprimer.
Comment puis-je mettre à jour mon référentiel pour refléter la nouvelle histoire de la sous-arborescence?
Ma première tentative a été d'utiliser filter-branch pour supprimer complètement le sous-arbre et tout l'historique.
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch upstream-project-dir' --prune-empty HEAD
Une fois que l'ancienne version du sous-arbre a été supprimée, j'ai pu rajouter le sous-arbre en utilisant le nouveau maître en amont. Cependant, cela n'a pas fonctionné car pour une raison quelconque, l'historique des validations apparaît toujours dans la sortie du journal git.
Mise à jour
J'ai écrit les étapes pour créer un exemple reproductible au minimum.
Créez d'abord un dépôt git vide.
git init test-monorepo cd ./test-monorepo
Créez un commit initial.
echo hello world > README git add README git commit -m 'initial commit'
Ajoutez maintenant une sous-arborescence pour un projet externe.
git remote add thirdparty [email protected]:teivah/algodeck.git git fetch thirdparty git subtree add --prefix algodeck thirdparty master
Faites des commits sur le monorepo
echo dont panic >> algodeck/README.md git commit -a -m 'test commit'
Essayez maintenant d'utiliser git filter-branch pour supprimer la sous-arborescence.
git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch algodeck' --prune-empty HEAD
Examinez la sortie du journal git, je m'attends à voir uniquement ma validation initiale.
git log
git gc --prune=now
supprimerais- je pas seulement les commits qui n'apparaissent pas dansgit log
?git log
, aucun argument et je vois toujours les vieux commits.Réponses:
vous avez déjà eu le mauvais commit de votre histoire et vous devez vous en débarrasser avant de continuer
supposons que votre
master
dernier commit ait été détourné et que vous n'ayez rien pu faire d'autre (je n'ai vraiment pas vos branches à vue, donc je dois supposer quelque chose pour commencer)vous pouvez passer à la validation précédente et repousser votre marqueur de branche de 1 pas en arrière (ou X pas en arrière) qui serait sans danger dans tous les cas, puis tirer à nouveau
par exemple
git checkout master~1
pour vérifier le commit du parent du maître, git avertit que nous sommes hors des succursalesgit branch master -f
pour forcer le checkout en cours à redevenir master, c'est-à-dire qu'il rembobine en fait la branche master vers son commit précédent (ou X commit précédent), et à partir d'ici, peu importe si l'amont a fait une force ou non, nous pouvons reprendre normalement, ou même revenir à l'étape ci-dessus si nécessaire, nous ne pouvons que tirer à nouveau le maître, sans rien perdre de l'amont (qui pour nous pourrait également être en lecture seule, nous ne pousserons rien pour cela)git checkout master
être sur notre branche maître "rembobinage", le même commit que nous faisons, mais maintenant être sur la branchegit pull
pour tirer à nouveau le maître (peut être avec ou sans--prune
), s'il est détourné en amont, nous reviendrons sur la bonne voie d'ici, sinon, nous obtiendrons le même que nous avions, si nous obtenons le même et n'était pas supposé, peut-être que nous besoin de revenir à la 1ère étape ci-dessus et de rembobiner plus de validations, par exemplegit checkout master~5
ou autre chose (au besoin)la source
git subtree
sur votre repo, nettoyez l'historique des commits pour cette télécommande:
si l'une de vos propres validations a une validation qui inclut le gros fichier, réécrivez votre historique afin que ce gros fichier ne soit plus référencé
Avec ces deux étapes, le gros fichier ne sera plus référencé par aucun commit dans votre référentiel.
Il sera également supprimé de votre disque dur à un moment donné, lorsque git exécutera son garbage collector et que les délais d'expiration des objets blob pendants seront atteints.
Si vous avez un besoin urgent de supprimer ce gros fichier dès que possible de votre disque dur:
Exécutez manuellement
la source