Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using git filter-branch for specific commits

Tags:

I'm trying to use the git filter-branch feature to remove a file that was recently updated and committed. I tried running the following command:

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch myfile' --prune-empty --tag-name-filter cat -- 6f7fda9..HEAD

However this only removes the file from the master branch, and I want it removed from all branches.

Starting with commit 6f7fda9 to HEAD I want the file removed. Is the command I'm running wrong?

like image 219
Spark323 Avatar asked Aug 09 '18 16:08

Spark323


People also ask

What does git filter branch do?

git-filter-branch can be used to get rid of a subset of files, usually with some combination of --index-filter and --subdirectory-filter .

What is a commit tree?

git-commit-tree is a low level command which commits a single tree object but does not perform any of the follow-up reference and Head work that git-commit does.

How do I remove sensitive data from git history?

You cannot remove sensitive data from other users' clones of your repository, but you can permanently remove cached views and references to the sensitive data in pull requests on GitHub by contacting GitHub Support.

What is the git commit command?

The git commit command captures a snapshot of the project's currently staged changes. Committed snapshots can be thought of as “safe” versions of a project—Git will never change them unless you explicitly ask it to.


1 Answers

Your requirements as stated are contradictory. Specifically

I want it removed from all branches.

and

Starting with commit 6f7fda9 to HEAD I want the file removed.

need to be reconciled. I suspect this comes down to an inaccurate understanding of commit ranges - which are only sort-of a thing in git.

Consider this commit graph:

x -- 6f7fda9 -- A -- B -- C -- F <--(master)
                 \                        ^(HEAD)
                  D -- E <--(branch)

So HEAD is at master which is at F; and there's a branch which was (apparently) created from A (after 6f7fda9 but before HEAD).

Now the question is, given this graph what does 6f7fda9..HEAD mean? And unfortunately, the answer isn't what a lot of people intuitively think.

6f7fda9..HEAD is short for HEAD ^6f7fda9 - meaning "everything reachable from HEAD but not reachable from 6f7fda9". "Reachable" means "the commit itself, and any commits you find by following parent pointers". So in this case, it means A, B, C, and F; but not x or 6f7fda9 (because they're reachable from 6f7fda9) and also not D, or E (because they aren't reachable from HEAD).

There are several ways to get filter-branch to process all the branches. For example you could

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch myfile' --prune-empty --tag-name-filter cat -- --all

But this will include all refs (not just all branches); if that's a problem

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch myfile' --prune-empty --tag-name-filter cat -- --branches

One other caveat - if you specifically don't want commits before 6f7fda9 rewritten, then you need to include one or more negative commit references. But assuming you do intend to include 6f7fda9 itself, you'd exclude its parent (not itself).

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch myfile' --prune-empty --tag-name-filter cat -- ^6f7fda9^ --branches

If 6f7fda9 is a merge, you'd have to list negative commit references for each of its parents.

like image 66
Mark Adelsberger Avatar answered Sep 28 '22 18:09

Mark Adelsberger