Imagine the following history:
       c---e---g--- feature
      /         \
-a---b---d---f---h--- master
How can I find when commit "c" has been merged into master (ie, find merge commit "h") ?
Imagine the following history:
       c---e---g--- feature
      /         \
-a---b---d---f---h--- master
How can I find when commit "c" has been merged into master (ie, find merge commit "h") ?
 
    
     
    
    Add this to your ~/.gitconfig:
[alias]
    find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
    show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"
Then you can use the aliases like this:
# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master
To see the merge commit's message and other details, use git show-merge with the same arguments.
(Based on Gauthier's answer. Thanks to Rosen Matev and javabrett for correcting a problem with sort.)
Your example shows that the branch feature is still available.
In that case h is the last result of:
git log master ^feature --ancestry-path
If the branch feature is not available anymore, you can show the merge commits in the history line between c and master:
git log <SHA-1_for_c>..master --ancestry-path --merges
This will however also show all the merges that happened after h, and between e and g on feature.
Comparing the result of the following commands:
git rev-list <SHA-1_for_c>..master --ancestry-path
git rev-list <SHA-1_for_c>..master --first-parent
will give you the SHA-1 of h as the last row in common. 
If you have it available, you can use comm -1 -2 on these results. If you are on msysgit, you can use the following perl code to compare:
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2
(perl code from http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/ , which took it from "someone at comp.unix.shell news group").
See process substitution if you want to make it a one-liner.
 
    
    git-get-merge will locate and show the merge commit you're looking for:
pip install git-get-merge
git get-merge <SHA-1>
The command follows the children of the given commit until a merge into another branch (presumably master) is found.
 
    
    That is, to summarize Gauthier's post:
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' <(git rev-list --ancestry-path <SHA-1_for_c>..master) <(git rev-list --first-parent <SHA-1_for_c>..master) | tail -n 1
EDIT: because this uses process substitution "<()", it is not POSIX compatible, and it may not work with your shell. It works with bash or zsh though. 
 
    
    I needed to do this, and somehow found git-when-merged (which actually references this SO question, but Michael Haggerty never added a reference to his very nice Python script here).  So now I have.
 
    
    Building on Gauthier's great answer, we don't need to use comm to compare the lists. Since we're looking for the last result in --ancestry-path which is also in --first-parent, we can simply grep for the latter in the output of the former:
git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1
Or for something snappy and reusable, here's a function to pop into .bashrc:
function git-find-merge() {
  git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1
}
 
    
    git log --topo-order
Then look for the first merge before the commit.
 
    
    For the Ruby crowd, there's git-whence. Very easy.
$ gem install git-whence
$ git whence 1234567
234557 Merge pull request #203 from branch/pathway
 
    
    I use below bash script which I place at path ~/bin/git-find-merge. It's based on Gauthier's answer and evilstreak's answer with few tweaks to handle corner cases. comm throws when the inputs are not sorted. grep -f works perfectly.
Corner cases:
~/bin/git-find-merge script:
#!/bin/bash
commit=$1
if [ -z $commit ]; then
    echo 1>&2 "fatal: commit is required"
    exit 1
fi
commit=$(git rev-parse $commit)
branch=${2-@}
# if branch points to commit (both are same), then return commit
if [ $commit == $(git rev-parse $branch) ]; then
    git log -1 $commit
    exit
fi
# if commit is a merge commit on first-parent path of branch,
# then return commit
# if commit is a NON-merge commit on first-parent path of branch,
# then return branch as it's either a ff merge or commit is only on branch
# and there is not a good way to figure out the right commit
if [[ $(git log --first-parent --pretty='%P' $commit..$branch | \
    cut -d' ' -f1 | \
    grep $commit | wc -l) -eq 1 ]]; then
    if [ $(git show -s --format="%P" $commit | wc -w) -gt 1 ]; then
        # if commit is a merge commit
        git log -1 $commit
    else
        # if commit is a NON-merge commit
        echo 1>&2 ""
        echo 1>&2 "error: returning the branch commit (ff merge or commit only on branch)"
        echo 1>&2 ""
        git log -1 $branch
    fi
    exit
fi
# 1st common commit from bottom of first-parent and ancestry-path
merge=$(grep -f \
    <(git rev-list --first-parent  $commit..$branch) \
    <(git rev-list --ancestry-path $commit..$branch) \
        | tail -1)
if [ ! -z $merge ]; then
    git log -1 $merge
    exit
fi
# merge commit not found
echo 1>&2 "fatal: no merge commit found"
exit 1
Which lets me do this:
(master)
$ git find-merge <commit>    # to find when commit merged to current branch
$ git find-merge <branch>    # to find when branch merged to current branch
$ git find-merge <commit> pu # to find when commit merged to pu branch
This script is also available on my github.
 
    
    My ruby version of @robinst's idea, works twice faster (which is important when searching for very old commit).
find-commit.rb
commit = ARGV[0]
master = ARGV[1] || 'origin/master'
unless commit
  puts "Usage: find-commit.rb commit [master-branch]"
  puts "Will show commit that merged <commit> into <master-branch>"
  exit 1
end
parents = `git rev-list #{commit}..#{master} --reverse --first-parent --merges`.split("\n")
ancestry = `git rev-list #{commit}..#{master} --reverse --ancestry-path --merges`.split("\n")
merge = (parents & ancestry)[0]
if merge
  system "git show #{merge}"
else
  puts "#{master} doesn't include #{commit}"
  exit 2
end
You can just use it like this:
ruby find-commit.rb SHA master
 
    
     
    
    This is the best way to find the commit in master:
[alias]
    find-merge = !"f() { git rev-list $1..master --ancestry-path --merges --reverse | head -1; }; f"
 
    
    I've had to do this several times (thanks to everyone that answered this question!), and ended up writing a script (using Gauthier's method) that I could add to my little collection of git utilities. You can find it here: https://github.com/mwoehlke/git-utils/blob/master/bin/git-merge-point.
 
    
    A graphical solution is to find it in gitk (using the “SHA1 ID” box) and follow the line of commits up to the merge commit.
 
    
    You can try something like this. The idea is to iterate through all merge commit and see if the commit "c" is reachable from one of them:
$ git log --merges --format='%h' master | while read mergecommit; do
  if git log --format='%h' $mergecommit|grep -q $c; then
    echo $mergecommit;
    break
  fi
done
