Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Now commit and things will be working as expected. 

Perform bash/shell operations on every commit (and rewrite history)

A few times I've needed to perform certain operations (like say delete a file that shouldn't have been added to the repo).  In my case, I was actually separating out multiple code bases from one repository into several.  Luckily, the repository contained separate folders, where each folder (which contained separate and independent projects), so basically I just had to move these folders into separate repositories... while keeping all history for the specific folder only.

This turned out to be fairly straightforward (see, not all things with git are difficult (smile)).

Basically, I created a repo for each project and pushed master (which contained all folders and all changes over the original repo history) to each repo (i.e. basically just created copies of the original repo).  I then checked out each of the just created repos and ran the following from bash (or git bash if you've installed it on windows):

Code Block
themeEmacs
git filter-branch --tree-filter 'ls | grep -v project1-folder | xargs rm -rf; rm -f .gitignore' HEAD

where project1-folder  is the folder that I wanted to keep for this specific repo.  ls | grep -v project1-folder | xargs rm -rf lists all folders EXCEPT project1-folder and then pipes to xargs which runs rm -rf on each (which deletes those other folders). You'll note that I also deleted .gitignore (which contained a whole bunch of ignores for each project - I'll recreate this for each new repo just with the specific ignores relevant to the new repo).

Now git filter-branch can be pretty destructive as it rewrites history, so it creates a backup before the operation.  Once you're happy with the your filtering you can remove this backup with:

Code Block
themeEmacs
rm -rf .git/refs/original/

We have a problem now... we've removed all of the other folders from repo history (which is what we wanted) but it's resulted in lots of empty commits (e.g. when anyone changed files within one of the now deleted folders, these commits are now empty but still existent).

Not to worry, git contains a command for just this case.  The following will go through each commit, and if its empty, will remove it:

Code Block
themeEmacs
git filter-branch --prune-empty

After it is completed, you should now have only those commits that changed files/folders within the actual folder you want to keep (e.g. project-folder1).

You'll also probably want to remove the backup refs (which git creates before pruning empty commits)

Code Block
themeEmacs
rm -rf .git/refs/original/

git can't checkout on windows due to filename too long...

...