如何从我的主存储库子树上的子项目中重新定义`filter-branch`?

时间:2016-10-05 00:01:48

标签: git git-submodules git-rebase git-subtree

如何从我的主存储库子树上的子项目中重新绑定filter-branch

对我来说,这是使用子模块执行的正常操作。我只想按照此处的描述进行正常的变换:Rebasing everyone onto changed git history after filter-branch

我所做的操作是在我的子项目上,在自己的存储库中。这是操作:

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch "some_folder/path" -r -f' \
--prune-empty --tag-name-filter cat -- --all

之后我将更改推送到子项目自己的存储库:

git push origin --force --all
git push origin --force --tags

现在我想将更改集成到我的主存储库中,我的子项目是子树。所以,这不是一个普通的存储库。为什么我没有在git子树上看到rebase选项?

对此的解决方案只有:git subtree: possible to change subtree branch/path in a forked repository?,删除它并读取它?

尝试

做的时候:

git subtree pull --prefix=subprojectFolder subprojectRemoteRepository.git 

输出结果为:

 * branch            master     -> FETCH_HEAD
fatal: refusing to merge unrelated histories

使用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

如何使它们相关?

执行--allow-unrelated-histories只会导致:

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...>

1 个答案:

答案 0 :(得分:1)

我正在应用此解决方案,而没有更方便的东西。

第1部分

  1. 要克隆subproject dedicated repository并结帐。
  2. 按我喜欢的方式执行filter-branch操作。
  3. 执行git push origin --force --all和标记。
  4. 第2部分

    1. 克隆main project存储库并在其上签出。
    2. 要执行与第1部分执行的完全相同的filter-branch,并执行删除当前子项目树,或使用bfg-repo-cleaner: / p>

      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
      
    3. 第3部分

      1. 最后读了刚刚清理过的子树:

        git clone mainRepository.git
        cd mainRepository
        git checkout master
        git subtree add --prefix=subprojectFolder subproject.git master
        git push
        
      2. 告诉每个人你的主要项目Rebasing everyone onto changed git history after filter-branch以及子项目专用克隆(如果有的话)。
      3. 结束

        1. 请注意,目前使用bfg-repo-cleaner,如果主项目中没有包含子项目名称的其他文件夹,则只能删除该文件夹。这是因为BFG将删除与subprojectFolder名称匹配的所有文件夹。指定仍在开发中的文件夹路径的能力:How to delete one folder / directory using BFG repo cleaner?。否则,您可以使用filter-branch删除项目的subtree

        2. 对于完全删除的事情,在完成存储库中的filter-branch之后,还可以从其他答案Why is my git repository so big?中做到这一点:

          rm -Rf .git/refs/original && \
              git reflog expire --expire=now --all && \
              git gc --aggressive && \
              git prune
          
        3. 列出最大的文件:

          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
          
        4. 在另一个答案How to remove unreferenced blobs from my git repo中,您可能希望在filter-branch拉后执行此操作。记得阅读原点。

          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 "$@"