I want to use subtrees in one of my projects, and I use the method described below here . I am having problems merging a subtree into my subproject when some files have been deleted from the subtree. It seems that deleting the file does not extend from the subtree integration branch to the main branch during merge.
I am running Git 1.9.1 on Kubuntu 14.04 and sub_project integrated as subtree in my main project.
Change one file and delete another file from my sub_project
Commit change
Overview of my main project
View the sub_project integration thread
Retrieve the modification (I see the modification of the modified file and the removal of the deleted file)
Checkout the master branch of my main project
git diff-tree -p sub_project_branch indicates that one file has been modified and one file has been deleted
Merge my subtree integration branch into the main branch (the remote file still exists, and the modification is integrated)
Here are the relevant commands:
Creating a project to be used as a subtree
$ mkdir sub_project $ cd sub_project $ git init $ touch toto $ echo "-----------------" >> toto $ echo "- toto file">> toto $ echo "-----------------" >> toto $ touch tata $ echo "-----------------" >> tata $ echo "- tata file">> tata $ echo "-----------------" >> tata $ git add toto tata $ git commit -m "Initial commit" $ echo "echo toto" >> toto $ echo "echo tata" >> tata $ git commit -am "Add content to file" $ cd ..
Creating a main project that will use a subtree
$ mkdir main_project $ cd main_project $ git init $ touch tutu $ echo "-----------------" >> tutu $ echo "- tutu file">> tutu $ echo "-----------------" >> tutu $ git add tutu $ git commit -m "Add tutu file"
Create subtree
$ mkdir sources $ git remote add sub_project_remote ../sub_project $ git fetch sub_project_remote $ git checkout -b sub_project_branch sub_project_remote/master $ git checkout master $ git read-tree --prefix=sources/sub_project/ -u sub_project_branch $ git commit -am "Integration of subtree"
Verifying that the subtree is well integrated
$ ls * tutu sources: sub_project $ ls sources/sub_project tata toto
Go to subtree to delete tata strong file>
$ cd ../sub_project $ echo "#EOF" >> toto $ git add toto $ git rm tata $ git commit -m "Add EOF and remove tata"
Return to main project to integrate subtree modifications
$ cd ../main_project $ git checkout sub_project_branch $ git fetch sub_project_remote $ git pull
Make sure tata is removed in subtree
$ ls * toto
Merge in the main branch
$ git checkout master $ git diff-tree -p sub_project_branch diff
Check after merging that tata has been deleted
$ ls sources/sub_project tata toto
I expected to see in the master branch modifying the file and deleting another file, but the deleted file still exists and is being tracked. Modification of the file was completed, but it seems that the deletion was not βmergedβ.
The behavior that I expect is the same as shown in the sequence of commands below, which performs exactly the same actions, except that they are executed in the branch instead of the subtree. Toto had to be changed and tata will no longer be (or at least will not be tracked anymore).
#!/bin/sh $ git init $ touch toto $ echo "-----------------" >> toto $ echo "- toto file">> toto $ echo "-----------------" >> toto $ touch tata $ echo "-----------------" >> tata $ echo "- tata file">> tata $ echo "-----------------" >> tata $ git add toto tata $ git commit -m "Initial commit" $ echo "echo toto" >> toto $ echo "echo tata" >> tata $ git commit -am "Add content to file" $ git checkout -b headers $ echo "#EOF" >> toto $ git add toto $ git rm tata $ git commit -m "Add EOF and remove tata" $ git checkout master $ touch tutu $ echo "-----------------" >> tutu $ echo "- tutu file">> tutu $ echo "-----------------" >> tutu $ git add tutu $ git commit -m "Add tutu file" $ git merge -m "Merge from headers branch" headers Merge made by the 'recursive' strategy. tata | 4 ---- toto | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 tata [master a9cad6d] Add EOF 1 file changed, 1 insertion(+) $ echo "#EOF" >> tutu $ git add tutu $ git commit -m "Add EOF" $ ls toto tutu
According to what I see, it seems that the merging of subtrees makes a copy instead of the real merge, which means that if the source file disappears, the corresponding target file is not touched, but not deleted.
Is this behavior correct, or is it my understanding of what subtree merging should do, is it wrong?
I also asked a question about the Git mailing list , but at the moment I have no answers.