threads / discuss / 18495

checkout/update boiler plate for --filter-index?

Subject: checkout/update boiler plate for --filter-index?

## tl;dr

3 messages between Mar 23, 2009 and Mar 24, 2009.

replies: 2people: 3as markdown or json

Marcel Cary· Mar 23, 2009, 21:33 UTC · lore
I'm trying to do a historical find-and-replace on my code:
git grep -F foo > files
git filter-branch --index-filter "
   cat `pwd`/files | xargs git checkout  --
   cat `pwd`/files | xargs sed -i 's/foo/bar/g; '
   cat `pwd`/files | xargs git update-index --
" ancestor..HEAD

When I instead use --tree-filter and skip the checkout/update-index, it works how I want (but it takes a while...). But when I use --index- filter, the resulting history shows the "foo" to "bar" change happening *after* new code is added, rather than originally adding "bar".

How can I checkout just a few files and update them to take advantage of the speed of index operations?

Marcel
Johannes Sixt· Mar 24, 2009, 07:21 UTC · re: Marcel Cary · lore

Re: checkout/update boiler plate for --filter-index?

Marcel Cary schrieb:
Show 16 quoted lines
> I'm trying to do a historical find-and-replace on my code:
> 
> git grep -F foo > files
> git filter-branch --index-filter "
>   cat `pwd`/files | xargs git checkout  --
>   cat `pwd`/files | xargs sed -i 's/foo/bar/g; '
>   cat `pwd`/files | xargs git update-index --
> " ancestor..HEAD
> 
> When I instead use --tree-filter and skip the checkout/update-index, it
> works how I want (but it takes a while...).  But when I use
> --index-filter, the resulting history shows the "foo" to "bar" change
> happening *after* new code is added, rather than originally adding "bar".
> 
> How can I checkout just a few files and update them to take advantage of
> the speed of index operations?

You cannot do that with the index filter because you need actual blob contents to operate on, but the index filter doesn't give you an opportunity to do that. The tree filter is the right filter to use. But you neither need 'git checkout' nor 'git update-index' in the filter - filter-branch calls them for you. (Oh, and get rid of that useless use of cat.)

-- Hannes
Jeff King· Mar 24, 2009, 07:43 UTC · re: Johannes Sixt · lore

Re: checkout/update boiler plate for --filter-index?

On Tue, Mar 24, 2009 at 08:21:06AM +0100, Johannes Sixt wrote:
Show 6 quoted lines
> You cannot do that with the index filter because you need actual blob
> contents to operate on, but the index filter doesn't give you an
> opportunity to do that. The tree filter is the right filter to use. But
> you neither need 'git checkout' nor 'git update-index' in the filter -
> filter-branch calls them for you. (Oh, and get rid of that useless use of
> cat.)

Well, you _could_ do it as an index-filter, which has the potential to be much faster if you are only operating only on a small subset of the files. But it's much less readable. Something like (totally untested):

  git filter-branch --index-filter '
    for i in `cat /path/to/files`; do
      hash=$(git cat-file :$i |
             sed 's/foo/bar/' |
             git hash-object -w --stdin)
      git update-index --add --cacheinfo 100644 $hash $i
    done
  '

I'm sure you could do even do it with a constant number of processes per commit by using update-index --index-info, hash-object --stdin-paths, and cat-file --batch. But it would probably be even less readable. ;)

Personally, I would probably just do a tree-filter for simplicity unless the repo size made it prohibitively slow.

-Peff

← back to recent threads