I'm not familiar with resolve, but I've used the others:
Recursive
Recursive is the default for non-fast-forward merges. We're all familiar with that one.
Octopus
I've used octopus when I've had several trees that needed to be merged. You see this in larger projects where many branches have had independent development and it's all ready to come together into a single head.
An octopus branch merges multiple heads in one commit as long as it can do it cleanly.
For illustration, imagine you have a project that has a master, and then three branches to merge in (call them a, b, and c).
A series of recursive merges would look like this (note that the first merge was a fast-forward, as I didn't force recursion):
However, a single octopus merge would look like this:
commit ae632e99ba0ccd0e9e06d09e8647659220d043b9
Merge: f51262e... c9ce629... aa0f25d...
Ours
Ours == I want to pull in another head, but throw away all of the changes that head introduces.
This keeps the history of a branch without any of the effects of the branch.
(Read: It is not even looked at the changes between those branches. The branches are just merged and nothing is done to the files. If you want to merge in the other branch and every time there is the question "our file version or their version" you can use git merge -X ours
)
Subtree
Subtree is useful when you want to merge in another project into a subdirectory of your current project. Useful when you have a library you don't want to include as a submodule.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…