How do I merge from another git branch, excepting some commits, and have sane/easily queried history?
git, git-merge
Solution
I think `git-cherry` is the command you are looking for.
git cherry -v master foo
This shows commits in `foo` that have not (yet) been merged into `master`.
$ git cherry -v master foo
+ 1cffcfb1d061d308e8d33c262e30282a26b195cb Added anotherFile.txt to foo
+ fe0599190a6953c970cd3f94e18ff0c282e89e2c Added foochange.txt to foo
+ 1b548eb45ff50e59f3522ee63edd0c177e842645 Added yetAnotherFile.txt to foo
$ git cherry-pick 1cffcfb1d061d308e8d33c262e30282a26b195cb
...
$ git cherry-pick 1b548eb45ff50e59f3522ee63edd0c177e842645
...
$ git cherry -v master foo
- 1cffcfb1d061d308e8d33c262e30282a26b195cb Added anotherFile.txt to foo
+ fe0599190a6953c970cd3f94e18ff0c282e89e2c Added foochange.txt to foo
- 1b548eb45ff50e59f3522ee63edd0c177e842645 Added yetAnotherFile.txt to foo
From the manual:
The ones that have equivalent change already in the upstream branch are prefixed with a minus (-) sign, and those that only exist in the head branch are prefixed with a plus (+) symbol:
Problem
Short version: I've got a `master` branch, which people are working on and committing to. Then I've got a branch off of `master`, call it `foo` which people are also working on and committing to. Periodically, I want to bring over some, but not all, of the changes from `foo` back to `master`. I would like some way for the history of `master` to be query-able for the presence and absence of commits from `foo`. This appears problematic. How do I do this? Long version: Create an example git repo like this: ``` cd /tmp && mkdir gitrepo && cd gitrepo/ && git init echo "Something shared" > myFile.txt && git add myFile.txt && git commit -m "Added myFile.txt to master" git checkout -b foo master echo "Something else shared" > anotherFile.txt && git add anotherFile.txt && git commit -m "Added anotherFile.txt to foo" echo "Something specific to foo" > foochange.txt && git add foochange.txt && git commit -m "Added foochange.txt to foo" echo "Something else shared again" > yetAnotherFile.txt && git add yetAnotherFile.txt && git commit -m "Added yetAnotherFile.txt to foo" git checkout master echo "Something specific to master" > masterchange.txt && git add masterchange.txt && git commit -m "Added masterchange.txt to master" echo "Specific to master" > masterchange.txt && git add masterchange.txt && git commit -m "Added masterchange.txt on master" ``` (All discussion from here forward assumes we're on `master`) Now we've got the situation where `foo` is two commits behind `master` and has three commits of it's own. At this point I want to bring back the first and third commits from `foo` to `master` but NOT the second. The fundamental issue is that the parent of the commit at the head of `foo` is the commit that I don't want to merge, but since a commit's parents are part of that commit's hash there's no way to preserve the hash of the commit at the head of `foo` without also creating a situation where `git branch --contains foo^` is true for master. For instance, if I did `git merge foo` it would merge all the commits from `foo` to `master`. After doing that I would be able to say `git branch --contains foo^` and it would say that both `foo` and `master` contain that commit. I tried then doing a `git revert foo^` but `git branch --contains foo^` still reports that `master` contains `foo^`. If I `git cherry-pick foo foo^^` the two relevant revisions, then I have the changes from those two revisions' diffs from `foo` applied in `master`, but `git branch --contains foo^` says that only branch `foo` contains that commit. What I'm trying to achieve here is some way to query the history (without manually correlating hashes stored as text in commit messages) so I can be able to see which commits have and haven't been merged into master. As mentioned, I know of several ways to get the state of master to be equivalent to what I want (cherry-pick, merge+revert, format-patch/am, diff/patch, etc.) what I'm looking for is some way to query the history for the information I need. I get that `git branch --contains` will probably not ever work in the way I want it to, but if there's some alternate way to query the history, that I haven't thought of, I'm all ears. Anyone have any ideas?