Search This Blog

Friday, December 9, 2011

HowTo: Remove Files and Squash Commits in Git/GitHub

Help.GitHub - Remove sensitive data
Git Magic - Chapter 5. Lessons of History
Git Ready - Squashing Commits

Both of these steps remove things permanently from a remote Git repository. If anyone has something checked out that you delete here, they will be really mad. Other than that, these are safe, and useful things to do.

Removing all traces of a file that should never have been in there comes up from time to time. Unlike posting to twitter, we can clean things up in Git and GitHub.

Removing commits can be useful. There are always too many commits, and 6 months from now, maybe 1 out of 20 are useful. Squashing commits together can make the repository commits valuable checkpoints in development.

Removing (squash) commits:
git rebase -i HEAD~15
# This will drop you into $EDITOR, with a number of commits starting with pick.
# Go to the second line, and change all but the first commit from pick to squash.
# Save the file....The squash will automatically happen.
# Clean up any merge conflict files with meld.
# Successfully rebased and updated refs/heads/master.
# You will then drop into $EDITOR. Add a new commit message to the last line of the file, and save.
git push origin master --force

Removing files from all commits:
git filter-branch --tree-filter 'rm -rf never/should/have-been-there'
git status
git push origin master --force
rm -rf .git/refs/original
git reflog expire --expire-now --all
git reflog expire --expire=now --all
git gc --prume=now
git gc --prune=now --aggressive

Important Note(s):

When removing something from a remote repo, "git push origin master" will fail. You can instinctively fix it by git pull, followed by git push -- don't do that.

I made this mistake, git pull when the git push fails...The howto didn't hit me over the head with this...

Git status will show your repository has a different number of commits than the remote.

If you git pull to clear the error, you have both your squashed and the old commits in the now messy remote repository.

[rick@montechristo openbenchmarks]$ git push origin master
To git@github.com:rickfoosusa/openbenchmarks.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:rickfoosusa/openbenchmarks.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes (e.g. 'git pull') before pushing again. See the
'Note about fast-forwards' section of 'git push --help' for details.

In this case, we want this (--force), a git pull will correct the first, and undo everything you wanted to remove leaving copies of both...:

[rick@montechristo openbenchmarks]$ git push origin master --force
Counting objects: 1148, done.
Delta compression using up to 6 threads.
Compressing objects: 100% (896/896), done.
Writing objects: 100% (1133/1133), 3.64 MiB | 233 KiB/s, done.
Total 1133 (delta 377), reused 766 (delta 208)
To git@github.com:rickfoosusa/openbenchmarks.git
+ 9c17e12...354f2a2 master -> master (forced update)

Important Note: If someone has checked out something that you remove, they will be really mad. This is a good time to recommend the "git blame" command -- it lets someone blow off steam without actually doing anything bad to you.

No comments:

Post a Comment