filter-branch
from a subproject on my main repository's subtree?To me this is a normal operation to be performed with submodules. I would just to do a normal rebase as described here: Rebasing everyone onto changed git history after filter-branch
The operation I did was on my subproject, on its own repository. This was the operation:
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch "some_folder/path" -r -f' \
--prune-empty --tag-name-filter cat -- --all
After it I pushed the changes to the subproject own repository:
git push origin --force --all
git push origin --force --tags
Now I want to integrate the changes on my main repository, where my subproject is a subtree. So, this is not a normal repository. Why I do not see a rebase option on git subtree?
The solution to this would be only this: git subtree: possible to change subtree branch/path in a forked repository?, to delete it and readd it?
When doing:
git subtree pull --prefix=subprojectFolder subprojectRemoteRepository.git
The output is:
* branch master -> FETCH_HEAD
fatal: refusing to merge unrelated histories
Using git subtree merge
:
git remote add subproject_remote subprojectRemoteRepository.git
git fetch --no-tags
git checkout master
git subtree merge --prefix=subprojectFolder subproject_remote/master
fatal: refusing to merge unrelated histories
How to make them related?
Doing --allow-unrelated-histories
just results in:
error: unknown option `allow-unrelated-histories'
usage: git subtree add --prefix=<prefix> <commit>
or: git subtree add --prefix=<prefix> <repository> <ref>
or: git subtree merge --prefix=<prefix> <commit>
or: git subtree pull --prefix=<prefix> <repository> <ref>
or: git subtree push --prefix=<prefix> <repository> <ref>
or: git subtree split --prefix=<prefix> <commit...>
I am applying this solution right now while there is not something more handy.
subproject dedicated repository
and checkout on it.filter-branch
operations as I like them.git push origin --force --all
and tags.main project
repository and checkout on it.To perform the exactly the same filter-branch
performed on Part 1, and also perform it removing the current subproject tree, or use the bfg-repo-cleaner with:
git clone --mirror mainRepository.git
java -jar bfg.jar --no-blob-protection --delete-folders 'subprojectFolder' mainRepository.git
cd mainRepository.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push origin --force --all
git push origin --force --tags
cd ..
rm -r mainRepository.git
Finally readd the just cleaned subtree:
git clone mainRepository.git
cd mainRepository
git checkout master
git subtree add --prefix=subprojectFolder subproject.git master
git push
Note that using bfg-repo-cleaner for now, you will only be able to remove the folder if there are no other folders on the main project with the subproject name. This is because the BFG will remove all folders matching the subprojectFolder
name. The ability to specify a folder path still in development: How to delete one folder / directory using BFG repo cleaner?. Otherwise you may use the filter-branch
to remove the project's subtree
.
For completely erase things do also this from this other answer Why is my git repository so big?, after finished the filter-branch
(s) on your repository:
rm -Rf .git/refs/original && \
git reflog expire --expire=now --all && \
git gc --aggressive && \
git prune
To list the biggest files use:
git rev-list --all --objects | \
sed -n $(git rev-list --objects --all | \
cut -f1 -d' ' | \
git cat-file --batch-check | \
grep blob | \
sort -n -k 3 | \
tail -n40 | \
while read hash type size; do
echo -n "-e s/$hash/$size/p ";
done) | \
sort -n -k1
From this other answer, How to remove unreferenced blobs from my git repo, you might want to do this after the filter-branch
pull. Remember to readd the origin.
git tag | xargs git tag -d && \
git remote rm origin && \
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/ && \
git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d && \
git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 \
-c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@"