Merging file in Git
I downloaded CakePHP 2.0 zip package from their homepage some weeks ago and started coding a website with it. Now I want to upgrade it to CakePHP 2.0.4. I know that I can download the similar package and replace the files manually, but thought that I should merge the version from GitHub to save me troubles in the future. I tried
git remote add github git://github.com/cakephp/cakephp.git
git merge tags/2.0.4
But it didn't work. All files are conflicted. For example:
Auto-merging lib/Cake/View/Scaffolds/form.ctp CONFLICT (add/add): Merge conflict in lib/Cake/View/Scaffolds/form.ctp
Can you tell me how to do this properly? I'm a newbie in both git, CakePHP, and MacOSX! Thanks.
I'm going to presume you downloaded CakePHP 2.0.0, unzipped it and then ran something like git init, git add ., git commit to make a repository. Maybe you did some edits on top of that (if you didn't, just throw it out, clone the github repo and work from that).
The important thing is that you have a repository that started at the zipball.
Now when you added the github remote and fetched, github briefly warned you "warning: no common commits". What that means is there is no commit root between the repository on Github and your local repository.
a1 -- b1 -- c1 -- d1 -- e1 -- f1 master r1 -- s1 -- t1 -- u1 -- v1 -- w1 github/tags/2.0.4
When it goes to merge, there is no relationship between the two repositories. The conflicts are because they both appear to add the same files with different content.
Simplest way around this is to rebase your work on top of the 2.0.4 tag. You do this by rebasing everything except the first commit where you added the zip file. Let's say your first commit is a1 and your branch is master.
First, make a tag at your master. If something goes horribly wrong you can restore to that tag.
git tag tmp/master master
Then do the rebase.
git rebase --onto tags/2.0.4 a1 master
Each commit will be rewritten as a commit off the 2.0.4 release.
a1 -- b1 -- c1 -- d1 -- e1 -- f1 tmp/master r1 -- s1 -- t1 -- u1 -- v1 -- w1 github/tags/2.0.4 \ - b2 - c2 - d2 - e2 - f2 - g2 - h2 master
Think of a rebase like saving each commit as a patch and reapplying them to another branch. You take the diff between a1 and b1 and commit that on top of w1 making a new commit b2. Then diff b1 vs c1 and commit that on top of b1 making c2. And so on.
If your first commit was not the unaltered zip file, all is not lost. You can use the same procedure, but you have to recover that first bit of work. First you need to extract a diff between your first commit and a clean 2.0.0.
git diff tags/2.0.0 a1 > first_commit.patch
Then make a new branch off the 2.0.4 tag to hold your new work.
git checkout tags/2.0.4 git checkout -b newmaster
Apply and commit the patch.
git apply first_commit.patch git commit -a
Now newmaster contains 2.0.4 plus your first bit of work.
Now rebase master like before, but on top of newmaster instead of directly on 2.0.4.
git tag tmp/master master git rebase --onto newmaster a1 master
You can delete newmaster.
git branch -d newmaster
PS This all becomes more clear if you can visualize the repository. On OS X, GitX(L) is an excellent way to see the repo.