Michael
Michael

Reputation: 5127

Exclude a single commit from a "git diff"

Morning all, Let's say I have a series of commits as follows:

I know I can use

$ git diff -c --binary abc000..def555 > /tmp/abc000_def555.patch

to produce a patch to upgrade a system from abc000 to def555.

But what if I wanted to (for reasons to dull to get into) exclude def333 from the patch - how can I do this? Note that I do not want to revert def333, its just that I do not want the patch to incorporate this commit.

Thanks

Upvotes: 22

Views: 8625

Answers (5)

Ramin Zaghi
Ramin Zaghi

Reputation: 81

Old question, however I needed to do this to visually inspect the difference between two commits and I wanted to exclude some of the commits.

The most effective and easy way I found was to first use the git-format-patch command to generate all the commits in patch files on disk in a dedicated directory; and then use a command to find and delete those files that contained commit numbers which I wanted to remove. Finally, I concatenated all the remaining patch files into a single file which is what the OP is asking for.

On a Linux system with Bash you can do the following:

git format-patch --full-index <start-commit>..<end-commit>
mkdir all_patches
mv *.patch all_patches/
cd all_patches/
rm -rf `egrep -lsr "commit1-to-exclude|commit2-to-exclude|commit3-to-exclude" . `
cat * >> final.diff

Upvotes: 0

Elijah Lynn
Elijah Lynn

Reputation: 13468

It is not possible to git diff and exclude one or more commits. You have to make a new branch, revert the unwanted commits, then diff it and make a patch:

git checkout --branch <branch-name>-diff-branch // Create a throwaway branch.
git revert <unwanted-sha> // Get rid of the unwanted commit. Do this as many times as necessary, you cannot revert multiple SHAs at once.
git diff > new.patch // Create your new patch.
git checkout - // Checkout previous branch, nice trick eh?!
git branch --delete --force <branch-name>-diff-branch // Delete the throwaway branch.

p.s. I didn't want to butcher torek's answer too much so I posted a new one that I think is more concise.

Upvotes: 8

Hrishi
Hrishi

Reputation: 7138

You could try using git rebase -i and then drop the commit you don't need. Another way is to cherry-pick the commits you need on a different branch.

Upvotes: 1

torek
torek

Reputation: 488453

Actually all git diffs are commit-pair-wise: the above compares the trees/files in abc000 against those in def555. If for instance def333 changes dir/file but there are no changes to dir/file between abc000 and def555 (e.g., the change in def333 is canceled out by something along the way) you might not see dir/file in there at all.

In general, though, changes made in def333 will have altered dir/file in a way that shows up when comparing the version in abc000 against the one in def555. So you will probably see that change.

The easiest way to get a diff that shows "what def555 would look like if def333 were reverted" is to do just that: create a tree (on a temporary branch) with the change reverted. To do it with an actual named branch, you might do something like this:

git checkout def555 # by ID, so that you get a "detached HEAD"
git checkout -b temp-branch
git revert --no-edit def333
git diff [options] abc000
git checkout somebranch; git branch -D temp-branch

What if you don't want a temp branch? Well, that's trivial: just don't create one. Get a "detached HEAD" as above, do the revert as above, and then git checkout somebranch. There's no temporary branch to delete, except for the unnamed one that git will warn that you are leaving behind ... which is just what you wanted.

Upvotes: 12

Manuel van Rijn
Manuel van Rijn

Reputation: 10305

I would say you create a new branch, cherry-pick the commits you need and then do the diff

Upvotes: 3

Related Questions