Suppose I have a project on MASTER branch with 100s of php files. To do a bug fixing in the project, i create a separate branch
git checkout -b bugfix
No, there doesn't exist a direct way. Though; you can select the files from branch you want to merge and overwrite them over existing ones in master branch. The commands in order shall be:
git checkout master
git show bugfix:login.php > login.php
git show bugfix:register.php > register.php
git add .
git commit -m "Select login and register from branch/bugfix"
Ok, the above method will "destroy" file history. There is an old discussion about the same in this mailing list.
From a technical standpoint, the thing that makes history matter (and why "set of commits in date order" is useless) is because it gives us a COMMON ANCESTOR! And that is the only thing that matters.
Now, what is fundamentally wrong with doing per-file history?
Now, if you've followed this argument, you should go "Aaahh! Obvious!".
Ignoring a whole lot of paragraphs; you'll find the workaround:
git diff commit..othercommit filename | git-apply --index && git commit
In your case, commit
= hash of you HEAD/master branch; and othercommit
= hash of bugfix branch.
There is no way to record a partial merge in Git, all merges must merge the entire root trees of all the commits being merged.
You can of course choose to resolve that merge by choosing the unchanged copy of one the files from one of the parents, but this is still a "full" merge and the changes in that file will be considered to have been merged when it comes to subsequent rebases or merges between the branches involved.
You can simulate the behaviour you want but what happens with the changes you did on the third file?
The changes on the third file remain in the commits on the branch but they will not be present in the merged commit, it's like the file was not modified on the branch at all.
This is how you can do it:
git checkout master
git merge bugfix --no-commit
The --no-commit
option tells git
to merge the files but stop before committing them. You can now inspect the files, change them, do whatever you want. In order to cancel the changes you did on index.php
you can run:
git checkout master -- index.php
Running git status
you can see that index.php
does not appear as modified any more (neither in the index or in the working tree). You can now git commit
and that's all.
There are two approaches:
The following solution is adopted from a blog post
It turned out that checkout can also be helpful in this matter. You can simply callout (checkout) those specific files from another branch:
# switch to the branch you want to be your merge destination
git checkout master
# checkout specific files from specific branch (e.g bugfix)
# format: git checkout <source branch> <file.1> <file.2> ... <file.N>
git checkout bugfix login.php register.php
# check the status
git status
# merge them in
git commit -m "your merge comment"
This is an easy alternative approach, but it only works if you have one commit per file (meaning every time you have changed a file, you have made one commit and then have moved to the next file). In this case you can simply bring those specific commits to the other branch (in your case the master branch):
# get which commit you want to take to the other branch (first 7 characters will do)
git log
# switch to the branch you want to be your merge destination
git checkout master
# bring specific commit to this branch (replace the 63344f2 with your own 7 character commit ID)
git cherry-pick 63344f2