J'ai actuellement un référentiel Git local, que je pousse dans un référentiel Github.
Le référentiel local a ~ 10 validations et le référentiel Github en est une copie synchronisée.
Ce que j'aimerais faire, c'est supprimer TOUT l'historique des versions du référentiel Git local, afin que le contenu actuel du référentiel apparaisse comme le seul commit (et que les anciennes versions des fichiers du référentiel ne soient pas stockées).
J'aimerais ensuite transmettre ces modifications à Github.
J'ai étudié la base de données Git, mais cela semble mieux convenir à la suppression de versions spécifiques ... Une autre solution consiste à supprimer le référentiel local et à en créer un nouveau, même si cela entraînerait probablement beaucoup de travail!
ETA: Il existe des répertoires/fichiers spécifiques qui ne sont pas suivis. Dans la mesure du possible, j'aimerais conserver le dépiste de ces fichiers.
Voici l'approche de la force brute. Il supprime également la configuration du référentiel.
Note: Ceci ne fonctionne PAS si le référentiel a des sous-modules! Si vous utilisez des sous-modules, vous devez utiliser par exemple rebase interactive
Étape 1: supprimer tout l'historique (Assurez-vous d'avoir une sauvegarde, elle ne peut pas être annulée)
cat .git/config # note <github-uri>
rm -rf .git
Étape 2: reconstruire le référentiel Git avec uniquement le contenu actuel
git init
git add .
git commit -m "Initial commit"
Étape 3: Appuyez sur GitHub.
git remote add Origin <github-uri>
git Push -u --force Origin master
La seule solution qui fonctionne pour moi (et maintient les sous-modules en fonctionnement) est
git checkout --Orphan newBranch
git add -A # Add all files and commit them
git commit
git branch -D master # Deletes the master branch
git branch -m master # Rename the current branch to master
git Push -f Origin master # Force Push master branch to github
git gc --aggressive --Prune=all # remove the old files
La suppression de .git/
provoque toujours d’énormes problèmes lorsque j’ai des sous-modules . Utiliser git rebase --root
provoquerait en quelque sorte des conflits pour moi (et cela prend du temps depuis que j’ai beaucoup d’historique).
Ceci est mon approche privilégiée:
git branch new_branch_name $(echo "commit message" | git commit-tree HEAD^{tree})
Cela créera une nouvelle branche avec un commit qui ajoute tout dans HEAD. Cela ne modifie rien d'autre, donc c'est totalement sûr.
L’autre option, qui pourrait s’avérer très laborieuse si vous avez beaucoup de commits, est une rebase interactive (en supposant que votre version de git soit> = 1.7.12): git rebase --root -i
Lorsqu'on vous présente une liste de commits dans votre éditeur:
Sauver et fermer. Git va commencer à rebaser.
À la fin, vous obtiendrez un nouveau commit racine combinant tous ceux qui suivront.
L'avantage est que vous n'avez pas besoin de supprimer votre référentiel et que, si vous avez des doutes, vous avez toujours un repli.
Si vous voulez vraiment détruire votre historique, réinitialisez master à ce commit et supprimez toutes les autres branches.
Variante de la méthode proposée par larsmans :
Enregistrez votre liste de fichiers non-enregistrés:
git ls-files --others --exclude-standard > /tmp/my_untracked_files
Enregistrez votre configuration git:
mv .git/config /tmp/
Puis effectuez les premières étapes de larsmans:
rm -rf .git
git init
git add .
Restaurez votre config:
mv /tmp/config .git/
Décompressez vos fichiers non suivis:
cat /tmp/my_untracked_files | xargs -0 git rm --cached
Puis commettez:
git commit -m "Initial commit"
Et enfin, appuyez sur votre référentiel:
git Push -u --force Origin master
Vous pouvez utiliser un _ superficiel clones (git> 1.9):
git clone --depth depth remote-url
Lectures supplémentaires: http://blogs.atlassian.com/2014/05/handle-big-repositories-git/
La méthode ci-dessous est exactement reproductible. Il n'est donc pas nécessaire de réexécuter le clonage si les deux côtés sont cohérents. Il suffit également d'exécuter le script de l'autre côté.
git log -n1 --format=%H >.git/info/grafts
git filter-branch -f
rm .git/info/grafts
Si vous voulez ensuite le nettoyer, essayez ce script:
http://sam.nipl.net/b/git-gc-all-ferocious
J'ai écrit un script qui "tue l'histoire" pour chaque branche du référentiel:
http://sam.nipl.net/b/git-kill-history
voir aussi: http://sam.nipl.net/b/confirm
git filter-branch
est l'outil de chirurgie majeure.
git filter-branch --parent-filter true -- @^!
--parent-filter
obtient les parents sur stdin et devrait imprimer les parents réécrits sur stdout; unix true
se termine avec succès et n'imprime rien, donc: pas de parents. @^!
est Git en abrégé pour "la tête commet mais aucun de ses parents". Ensuite, supprimez toutes les autres références et appuyez à loisir.
Supprimez simplement le dépôt Github et créez-en un nouveau. De loin l'approche la plus rapide, la plus simple et la plus sûre. Après tout, qu’avez-vous à gagner à exécuter toutes ces commandes dans la solution acceptée lorsque tout ce que vous voulez, c’est la branche principale avec un seul commit?
Ci-dessous, un script adapté de la réponse de @Zeelot. Il convient de supprimer l'historique de toutes les branches, pas seulement de la branche principale:
for BR in $(git branch); do
git checkout $BR
git checkout --Orphan ${BR}_temp
git commit -m "Initial commit"
git branch -D $BR
git branch -m $BR
done;
git gc --aggressive --Prune=all
Cela a fonctionné pour mes besoins (je n'utilise pas de sous-modules).
Ce que j'aimerais faire, c'est supprimer TOUT l'historique des versions du référentiel Git local, afin que le contenu actuel du référentiel apparaisse comme le seul commit (et que les anciennes versions des fichiers du référentiel ne soient pas stockées).
Une réponse plus conceptuelle:
git automatiquement garbage collecte les anciens commits si aucun tag/branche/ref ne les pointe. Il vous suffit donc de supprimer toutes les balises/branches et de créer un nouveau commit Orphan, associé à toute branche - par convention, vous laisseriez la branche master
pointer sur ce commit.
Les anciens commits inaccessibles ne seront plus jamais vus, à moins qu’ils ne creusent avec des commandes git de bas niveau. Si cela vous suffit, je vais en rester là et laisser le GC automatique faire son travail à tout moment. Si vous voulez vous en débarrasser immédiatement, vous pouvez utiliser git gc
(éventuellement avec --aggressive --Prune=all
). Pour le référentiel git distant, vous n'avez aucun moyen de le forcer, sauf si vous disposez d'un accès Shell à leur système de fichiers.