How to move a subdirectory from a branch in one git repository to a branch in a different repository, preserving history?

*爱你&永不变心* 提交于 2021-02-08 03:39:27

问题


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 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?


回答1:


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



回答2:


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
    


来源:https://stackoverflow.com/questions/7434290/how-to-move-a-subdirectory-from-a-branch-in-one-git-repository-to-a-branch-in-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!