Comment réparer une sous-arborescence git après que la force du projet en amont a été poussée sur le maître?

13

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.

  1. Créez d'abord un dépôt git vide.

    git init test-monorepo
    cd ./test-monorepo
    
  2. Créez un commit initial.

    echo hello world > README
    git add README
    git commit -m 'initial commit'
    
  3. 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
    
  4. Faites des commits sur le monorepo

    echo dont panic >> algodeck/README.md
    git commit -a -m 'test commit'
    
  5. 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
    
  6. Examinez la sortie du journal git, je m'attends à voir uniquement ma validation initiale.

    git log
    
csnate
la source
Avez-vous essayé de git gc --prune = maintenant pour supprimer les anciens commits? Existe-t-il des références aux validations de l'ancienne version?
Damiano
1
Je n'ai pas encore essayé, mais ne git gc --prune=nowsupprimerais- je pas seulement les commits qui n'apparaissent pas dans git log?
csnate
l'utilisation de git branch -all (que je suppose que vous utilisez pour voir les "anciens" commits) devrait également montrer les commits sans rapport avec votre branche actuelle.
Damiano
1
En fait, je faisais juste git log, aucun argument et je vois toujours les vieux commits.
csnate
Pouvez-vous poster votre git log --pretty --all --graph? Juste pour comprendre votre situation
Damiano

Réponses:

0

vous avez déjà eu le mauvais commit de votre histoire et vous devez vous en débarrasser avant de continuer

supposons que votre masterdernier 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
git branch master -f
git checkout master
git pull
  1. git checkout master~1 pour vérifier le commit du parent du maître, git avertit que nous sommes hors des succursales
  2. git 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)
  3. git checkout master être sur notre branche maître "rembobinage", le même commit que nous faisons, mais maintenant être sur la branche
  4. git pullpour 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 exemple git checkout master~5ou autre chose (au besoin)
arhak
la source
Je ne pense pas que cela fonctionnera avecgit subtree
csnate
@csnate, il est possible de vérifier les validations précédentes d'une subrepo et de suivre une procédure très similaire, si vous créez un MCVE, il serait plus facile de vous dire les commandes exactes à suivre stackoverflow.com/help/minimal-reproducible-example
arhak
Je vais essayer de créer un exemple de dépôt sur GitHub.
csnate
J'ai créé un ensemble d'étapes dans la question d'origine qui montre le problème.
csnate
0
  1. sur votre repo, nettoyez l'historique des commits pour cette télécommande:

    git fetch upstream
    
  2. 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é

    # using one or more of the following commands :
    git rebase --interactive
    git filter-branch
    ...
    

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

git gc --prune=now
LeGEC
la source