How to remove all occurences of a file in index, from all git commits

耗尽温柔 提交于 2019-12-13 05:37:09

问题


First time using git here. I accidentally used "git init" without a .gitignore file so I have a bunch of gradle/ and build/ files in my commits. I am using "git ls-tree -r master" to show all files in the index. Instead of checking out every single previous commit and using "git rm --cached " to remove all the unnecessary build and gradle files, how do I remove all occurences of it through all previous commits?

Edit: Is there a way to remove every directory and files in all commits and only keep the src directory?


回答1:


You probably really do want the filter-branch command rather than rebase. Either way there are several items to be aware of:

  • You can't change any existing commits, ever.
  • Therefore, both rebase and filter-branch don't. Instead, they copy commits. Now you have twice as many commits! Wait, what?!
  • But Git can and will—eventually—remove what it calls unreferenced objects (commits and their corresponding files), and you can speed this up in various ways if necessary.

So this is what both rebase and filter-branch do: they copy the commits, and before committing the copy, allow some change(s). Then, having committed the (slightly different) copies, they move the references—the branch and tag names—to the copies.

With that in mind, there are several more items to consider:

  • Only filter-branch copies and moves tags, and it only does so if you provide a --tag-filter. (If you have no tags, this does not really matter, obviously.) And, when filter-branch copies signed annotated tags, it ditches their signatures: they become unsigned. Otherwise it would have to pester you to manually re-sign them all, and filter-branch is designed to be fully automated.
  • Because filter-branch is designed to be automated, and because it is designed to be able to run on every commit in a repository, it (a) tends to be slow and (b) has a lot of complicated options meant to speed it up. If you don't have that many commits, this is not that big a deal. If you do, it pays off to study how to use its many options to speed it up.
  • Because both commands copy commits, if anyone else has a copy of the repository, you're making a bunch of work for them too: they need to switch over to the copies. If they don't, they can re-introduce all the original commits, and then you are back to having twice as many.

Now you're ready for the linked question and its filter-branch answer. See this other answer to a related question as well, though, for instructions on using --tag-name-filter and some of the speed-up options.

Note that git rm -f --cached --ignore-unmatch works on directory (or "folder") names as well as on plain file names. The --tree-filter (mentioned in other answers on the second-linked page) can be used instead of the --index-filter, and it's more convenient for complex operations, but it is much slower (exact slowdown varies based on OS, size of repo, SSD vs spinning-media storage, etc., but "about 100x slower" is a good starting estimate) than using the --index-filter.



来源:https://stackoverflow.com/questions/38650355/how-to-remove-all-occurences-of-a-file-in-index-from-all-git-commits

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