2

I've got a directory containing utility libraries that were developed in a branch in one git repository, but it turns out they really belong in a different directory in a different project. I've read through and attempted Greg Bayer's Moving Files from one Git Repository to Another, Preserving History multiple times, but I'm unable to preserve history. I'm attempting to do this all under non-master branches to be more safe as the project is not ready to merge back to master yet anyway.

Here's what I'm doing so far:

Preparing the "DirectoryName" directory to be moved from branch "SomeBranch" of "Repo1" repository:

cd ~/Desktop git clone [email protected]:username/Repo1.git cd Repo1 git checkout -b SomeBranch origin/SomeBranch git remote rm origin git filter-branch --subdirectory-filter DirectoryName mkdir DirectoryName git mv *.php *.txt DirectoryName git add DirectoryName git commit -m "Stripped everything down to just DirectoryName." 

Merging the "DirectoryName" directory into the "SomeBranch" branch of the "Repo2" repository:

cd ~/Desktop git clone [email protected]:username/Repo2.git cd Repo2 git checkout -b SomeBranch origin/SomeBranch git remote rm origin git remote add Repo1 ../Repo1/ git pull Repo1 SomeBranch git remote rm Repo1 

When I do this I can successfully strip everything down to "DirectoryName" in Repo1 (and I can pull it over to Repo2 as well), but the history is lost. If I do a git log -- DirectoryName or git log -- DirectoryName/SomeFile.php, I only see the "Stripped everything down to just DirectoryName." commit). So, clearly something is wrong with my git filter-branch command, but I'm not familiar enough with it to figure out what.

Any suggestions would be greatly appreciated as we're undergoing some fundamental changes to our codebase, so I'll need to be doing this relatively frequently for a while as stuff moves around (but we want to preserve the history).

Update: As I mentioned git log -- DirectoryName (or git log -- DirectoryName/SomeFile.php; either in Repo1 or Repo2) does not show any commits other that the "Stripped everything down to just DirectoryName." commit, but if I do git log I see the correct commit history. Am I just using git log incorrectly or is there some corruption that's causing the commits to not show up correctly?

Another Update: git log -- DirectoryName does show the correct commits in my original, unmodified Repo1, but it does not show the correct commits after the git filter-branch (and I've tried git filter-branch --subdirectory-filter DirectoryName -- --all but that mucks with the "master" branch as well and doesn't appear to be necessary... same result). That said, the commit history is there after running git filter-branch, I can see it all with git log master.. it just no longer seems to pertain to the directory or the files. Any ideas?

2 Answers 2

2

It sounds as if what you've done is fine, it's just a misunderstanding about git log that's causing problems.

git just stores the state of the tree at each commit, rather than recording the changes that took the tree from the state in one commit to the next. If you're using git log to find the history of a particular file or directory, however, you can tell it to try to look for renames when the history of the file appears to run out. You can do that with:

git log --follow -- DirectoryName 

Or if that doesn't work, try it for just a single file, e.g.

git log --follow -- DirectoryName/whatever.txt 
Sign up to request clarification or add additional context in comments.

1 Comment

Yup, that was it! I just was missing the fact that git log wouldn't automatically follow renames and such (and using git filter-branch necessitates renaming since the files then end up in the root of the tree).
0

Here's how I'd do it:

  1. Create patches for all the commits that touch the files in the subdir:

    $ c=1; git log --format=%h -- subdir/*|tac|while read commit; do git format-patch --stdout -1 $commit > $(printf '%04d' $c).patch c=$((c+1)) done 

    Note that if there are single commits that touches both files in the subdir and outside of subdir then the patch will also include the diff on the other file so you'll have to prune those hunks, or do a filter branch to remove those files once you done step two below:

  2. Use git am to apply the patches on the branch in the other repo:

    $ git am *.patch 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.