4

So I have done a merge of another repository into a subdirectory of the current repository, as:

git remote add -f Bproject /path/to/B
git merge -s ours --no-commit Bproject/master
git read-tree --prefix=dir-B/ -u Bproject/master
git commit -m "Merge B project as our subdirectory"

There seem to be subtle problems, though. When I do

git log dir-B/

the result is just the "Merge B project as our subdirectory" message. How do I get the log information I want, that is, the imported history of dir-B?

U2EF1
  • 12,907
  • 3
  • 35
  • 37
  • Let's start with defining what kind of log information you _want_? :) – favoretti Oct 25 '12 at 01:35
  • 1
    @favoretti The history of dir-B. I would have expected at least `git log --follow dir-B/` to help here, but that still only shows the merge commit. – U2EF1 Oct 25 '12 at 01:40
  • Well, that's exactly how you merged, --no-commit, so essentially you just squashed it all and commited in one go. – favoretti Oct 25 '12 at 01:43
  • When you run `git show` on the commit, does it have one or two parent SHAs? – r3m0t Oct 25 '12 at 01:46
  • @favoretti The documentation says that just forestalls the commit until two lines later, it says nothing about squashing one of the merged trees. – U2EF1 Oct 25 '12 at 04:17

2 Answers2

4

Your merge commit shows example.txt in BProject/master as being renamed to dir-B/example.txt. git log doesn't follow the history of a file/directory past renaming unless the --follow option was used:

--follow
Continue listing the history of a file beyond renames (works only for a single file).

If you are really desperate to get the diffs showing correctly, you can rewrite the Bproject/master history as though the project has always been in a directory dir-B, then do an ordinary merge. This will mean the SHAs of the merged history bear no relation to the ones on Bproject/master! The timestamp, author and commit message will all retain their original values though.

If you want to do this, I would suggest cloning Bproject seperately first, then running this in that clone:

git-filter-branch manpage

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

After you've confirmed the new history looks correct, you can add your rewritten version as a remote to your main project and merge it in using an ordinary merge.

r3m0t
  • 1,850
  • 16
  • 21
  • I know about `--follow`, it doesn't help. I'd be happy to completely rewrite history if it will give me a usable `git log`. – U2EF1 Oct 25 '12 at 04:16
  • Hey U2EF1, did you ever try rewriting history and did it fix your problem? – mwhite Apr 05 '13 at 05:04
  • 2
    @mwhite, `--follow` only follows the first parent. You need to make a new commit on `BProject/master` which has everything being moved into a subdirectory, then merge that commit with `AProject/master`. – r3m0t Apr 05 '13 at 09:49
  • 3
    If you try this on OS X, note that you’ll have to replace `\t` in the sed command with Ctrl-V + tab (see [How can I insert a tab character with sed on OS X?](http://stackoverflow.com/a/5398430/1534401)). – Frederik Jan 22 '15 at 10:41
0

Based on r3m0t's idea of rewriting history, following lines did the whole trick for me, to merge the other git repository as new branch into my existing one into a sub directory:

(working in git-sh I could omit the leading 'git' for commands)

co -b my-new-branch 
remote add -f origin-my-old-standalone-project ../my-old-standalone-project/
pull origin-my-old-standalone-project master
mkdir my-new-subdir
ci -am "merge 'old' standalone project as new branch 'my-new-branch'"
git filter-branch --index-filter \
        'git ls-files -s | sed "s%\t\"*%&my-new-subdir/%" |
                GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
                        git update-index --index-info &&
         mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE"' HEAD

After that I had both: A history for individual files in the new sub directory as if they have been there all the time, and the normal history in the main directory, as if the new files in the sub directory always had been there. (As you can see, no read-tree or any other not daily used commands are necessary, the 'filter-branch' does the whole trick.) IDE's are able (resp. should be; successfully tested PyCharm) to work normally with the result.

After that you should be able to merge your branches as normally, getting all projects into one.

tl;dr: --follow works as expected, normal history also, after executing above 6 commands to merge old git project into new branch and sub directory of other git project

Jaleks
  • 561
  • 5
  • 19