4

I'm trying to rename a directory that was introduced six commits ago and in all subsequent commits. These commits have not been pushed.

What have I tried?

  • I've tried using git filter-branch with an mv old new command, but this fails on commits before HEAD~6 because the directory doesn't exist.
  • I've tried git rebase -i HEAD~6, editing each commit, but I can't use mv old new because git's locking the file, nor can I rename it in Windows Explorer.
  • I've tried the same rebase with cp -R old new; rm -rf old; git add new but this creates merge conflicts on HEAD~4 and above.

It may be worth noting that the commit on which this directory was introduced is the first commit in this branch (the branch is six commits ahead of master) and that I haven't touched master since I branched out.

I've also read this question.

What's the best way to do this?

Community
  • 1
  • 1
wchargin
  • 15,589
  • 12
  • 71
  • 110
  • why not simply start a new branch (at master) and then do a simple swap between the old and the new branches at ~N and pick off the 6 commits in a row (e.g. cherry-pick & git mv old new & commit). It may not be 'fast' but it would be quite quick. – Philip Oakley Oct 07 '13 at 17:06
  • @PhilipOakley excellent suggestion! I hadn't used `cherry-pick` before but that worked quite well. If you post as an answer I'll accept. – wchargin Oct 07 '13 at 17:30

3 Answers3

4

git filter-branch should work fine; just make the mv command fail gracefully by appending || true. For example, to rename baz/ to foo/bar/baz/:

git filter-branch --force --tree-filter \
    'mkdir -p foo/bar; mv baz foo/bar/ || true' \
    --tag-name-filter cat -- --all
z0r
  • 8,185
  • 4
  • 64
  • 83
2

https://git-scm.com/docs/git-filter-branch states:

To move the whole tree into a subdirectory, or remove it from there:

git filter-branch --index-filter \
    'git ls-files -s | sed "s-\t\"*-&newsubdir/-" |
        GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
            git update-index --index-info &&
     mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD
Max
  • 1,068
  • 1
  • 10
  • 15
  • Thanks for your answer. Could you please explain how it works? In particular, what is the `GIT_INDEX_FILE` environment variable used for? (I get what the replacement pipeline does, but not the destination.) – wchargin Sep 19 '16 at 17:41
  • I'm not sure, trying to find out the details.. for now just copy pasting the examples. And it does work indeed. – Max Sep 19 '16 at 17:53
0

Why not simply start a new branch (at master) and then do a simple swap between the old and the new branches at ~N and pick off the 6 commits in a row.

For example git cherry-pick & git mv old new & git commit.

It may not be 'fast' but it would be quick enough with only 6 commits to fix.

Philip Oakley
  • 13,333
  • 9
  • 48
  • 71