Klaas van Schelven
Klaas van Schelven

Reputation: 2528

How to remove a file from git history while preserving (manually resolved) merges?

I would like to remove a particular file from the git history entirely. It's been added a while ago; since that point branching has occurred, as well as merges, some of which needed manual intervention.

The particular file is not involved in any of the merge problems. However, when I try to rewrite history, git makes me redo the work of resolving merges that have already been resolved originally. How can I avoid this?

A repo that exemplifies the problem can be constructed like so:

# intitial setup
mkdir rebase-across-manually-resolved-merge-conflicts
cd rebase-across-manually-resolved-merge-conflicts/
git init

# root commit, w/ garbage
echo "foo" > foo.txt
echo "unrelated-garbage" > unrelated-garbage.txt
git add foo.txt unrelated-garbage.txt 
git commit -m "initial checkin with undesirable content"

# branch a
git checkout -b branch-a
echo bar > foo.txt
git add foo.txt 
git commit -m "foo must be bar"

# branch b
git checkout master
git checkout -b branch-b
echo baz > foo.txt 
git add foo.txt 
git commit -m "foo must be baz"

# merging both branches into master; manual resolution of conflicts
git checkout master
git merge branch-a
git merge branch-b
echo barz > foo.txt
git add foo.txt 
git commit  -m "Merge branch 'branch-b' (manual resolution of merge conflicts)"

The result will look something like this:

*   4b874d0 (HEAD -> master) Merge branch 'branch-b' (manual resolution of merge conflicts)
|\  
| * 16e2bc4 (branch-b) foo must be baz
* | fa7418a (branch-a) foo must be bar
|/  
* ff8aa1b initial checkin with undesirable content
git rebase -r -i --root  # in the editor, change "pick" to "edit" for the line "initial checkin w..."
git rm unrelated-garbage.txt 
git commit --amend -m "initial checkin with no undesirable content"
git rebase --continue

This fails like so:

# Auto-merging foo.txt
# CONFLICT (content): Merge conflict in foo.txt
# Could not apply 819e457... branch-b # Merge branch 'branch-b' (manual resolution of merge conflicts)

An attempt with git rebase -p -i --root (using the deprecated -p option) is similarly unsuccessful.

I would like to have a fully automated solution... my real situation has many more merges and manual resolutions of those than the above example.

Upvotes: 0

Views: 21

Answers (2)

Klaas van Schelven
Klaas van Schelven

Reputation: 2528

Found it... not using rebase works

git filter-branch --force --index-filter \
  "git rm --cached --ignore-unmatch unrelated-garbage.txt" \
  --prune-empty --tag-name-filter cat -- --all

Upvotes: 0

DustInComp
DustInComp

Reputation: 2716

Try

git filter-branch --tree-filter 'rm -f unrelated-garbage.txt' HEAD

as described on https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History. Do note the "Caution" warning in that section. You might want to make a backup first.

Upvotes: 1

Related Questions