There are lots of ways to do that, depending on the precise results you want.
If you want the difference between two specific, already-existing commits (perhaps constrained to specific files / directories as well), git diff
will do it:
git diff rev1 rev2
or:
git diff rev1 rev2 -- path1 path2 ... pathN
If you want changes whose commits were within a specific date range, excluding changes outside of that range, it's a bit more complex. For instance, consider the following graph fragment:
... - D - E - F - G - J - K ...
\ /
H - I
Suppose further that the date on commit D
is "last Wednesday", but the date on commit E
is "two months ago", because commit E
was forward-ported (rebased or similar) from something done much earlier. Meanwhile commits F
and G
are recent, as is H
, but I
is also forward-ported from earlier like E
, and J
and K
are also recent, but you decide that K
is too recent. The commits you want are therefore D
but not E
; F
and G
; and H
but not I
.
In this case, to get all those changes (and no others) as a single patch, you will need to make a new branch starting just before D
into which you cherry-pick (or equivalent) each of those commits. You can cherry-pick them individually, then use git diff
to generate a patch from "just before D
" to "final result". In this case there is still a one-line(ish) way to do it since you're not picking up any merges:
git checkout -b deliver D^ && git cherry-pick \
$(git rev-list --since=... --until=...) && \
git diff D^ HEAD [-- paths]
Here, we use git rev-list
to pick the desired commits and feed the resulting SHA-1s to git cherry-pick
, which adds them on the new branch (deliver
) created starting from commit D^
. Assuming all goes well—not necessarily a good assumption—the final git diff
compares D^
, our starting point, with HEAD
, the result after all the cherry-picking.
(This can be simplified, if you call it simplification at least :-) , by creating the deliver
branch after commit D
since we plan to include it. I assume, however, that the --since
and --until
values are how you decided which commits to include in the first place, so I think it's a bit clearer this way.)
This all falls apart if you plan to include the merge-commit J
here: merge commits can be an "evil merge" (see here and here for details), and these cannot be simply cherry-picked. So if you do have some fancy requirements that require running git rev-list
to choose commits to include, check carefully. (Note that you can automate finding merges with --merges
.)