Delete a file from from all commits up to first branch point but not delete it from local file system

40 views Asked by At

Say you cloned a repository, then you created a new branch and did several commits on this branch ( without creating new branches or pushing to any remotes ). In some of these commits you introduced (committed) a file fileA by a mistake. Now, how can you remove that file from the history, but not from the local file system (i.e. keep the file as untracked)? Also assume that the name of the parent branch is not known (in order to completely automate the process).

1

There are 1 answers

0
Håkon Hægland On

We here use git filter-branch to remove the file from the index. It is important that we only use git filter-branch for the commits up to the first branch point; if not, we may not be able to merge the branch back into the original parent, and we could also accidentally delete a file with the same name in the parent branch.

A difficulty arises if we assume the name of the parent branch to be unknown. However, this can be resolved using git branch --contains:

filename=fileA
# git filter-branch will delete the local copy also, see 
# http://stackoverflow.com/q/33333200/2173773. So take a backup first.
cp "$filename" "$filename".bak 
readarray -t revlist < <(git rev-list HEAD)
sha1=""
for sha in "${revlist[@]}" ; do
    readarray -t branches < <(git branch --contains "$sha")
    # if there are more than a single branch that contains this commit
    # we have reached the branch point
    if (( ${#branches[@]} > 1 )) ; then
        sha1="$sha"
        break
    fi
done

git filter-branch -f --index-filter \
  "git rm --cached --ignore-unmatch $filename" "$sha1"..HEAD

# restore backup file
mv "$filename".bak "$filename"