How to Shrink/Cut a Git Repo

半城伤御伤魂 提交于 2019-11-30 14:15:36
Emil Sit

The best step-by-step instructions can be found on the Git SCM historical blog post "Replace Kicker" or in the Git book's chapter on "Replace".

The short summary is this:

  • Create a new branch that is at the point where you want to cut, say git branch history hash.
  • Push the history to a new repository.
  • Create a new base using git commit-tree.
  • Rebase your post-history commits onto your new base.
  • Push your new truncated master branch up to the server.
  • People can then use git replace to re-connect the history together.

The original post explains it much better with pictures.

When dealing with complex histories involving merges, this may not work well, depending on how well git rebase --onto works with --preserve-merges. You should obviously test well before proceeding.

Disclaimer: You should do this with a test repo first, since the commands listed here can destroy your data.

You can edit (i.e. let a script edit) the history via the fast-export mechanism. The first step is to run git fast-export --signed-tags=strip --no-data --full-tree --export-marks=export.marks branch1 branch2 [...] branchN > commits.fi. Now you have a fast-import stream of all your branches. In this stream, you can drop a commit by deleting the lines from commit refs/... to the trailing newline. You need also to remove the from :<mark> line (and also merge :<mark> lines if your new history starts with a merge) from your then new "first" commits.

To aid this process, you should look into the revision graph, and take revisions where no merges crosses their history. In the following graph, A, D and F are good candidates to start with. B or C do have the problem, that the successor D does also depend on G and A.

A ---- B ---- C ---- D --- E ---- F
  \                /  \     \   /
   \--- G ------- H    \--I--J-/

With the export.marks file you can translate the commit ID to mark numers in the stream.

You need to give your branches new names, since git fast-import won't accept the new history, because the new branches don't contain commits from the existing ones.

After you created the new history, you need to import it with git fastimport < manipulated-history.fi into your existing repo.

Now it is time to check if the import was correct. For this you need to clone the repo into a temporary one, and in this temporary repo you create for each newly created commit a graft so that it has the same parent revisions like before. Afterwards you run git filter-branch newBranch1 newBranch2 [...] newBranchN. The import was correct if each newBranch now stays at the same commit as the corresponding branch.

When everything worked so far, you can create a new repo and pull the newBranch-branches from the first working clone int it, and make it the new working repo. Also note that you should not leave any repos with grafts anywhere, since grafts can cause harm.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!