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 git@github.com: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 git@github.com: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 th开发者_开发百科e 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?
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
Here's how I'd do it:
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:
Use git am to apply the patches on the branch in the other repo:
$ git am *.patch
精彩评论