简体   繁体   中英

Find files that changed specifically in a branch

I have a git repository in which I usually work on two branches, a public branch, and a private branch, the latter following closely the public branch, but with a few extra additions.

Is there a way to find the changes since a given commit that are specific to the private branch ?

The closest I can think of is to do something on the lines of:

git diff base..public > pub.diff
git diff base..private > private.diff
interdiff pub.diff private.diff

This works, but it's not that robust, and I'm sure it's possible to do that with git in a better way.

This is essentially how the branches look (with many more merges):

...A---B---C---D---E---F---G---H public
    \           \           \
     A'--I---J---D'--K---L---G'--M private

For instance, let's assume that base above is D in this scheme. Just running

git diff D'..M

will also give me the results of the merge commit G' . I'd like to avoid that, and have something robust across any numbers of merges.

Because git diff

is about comparing two endpoints, not ranges

This might not be possible ( git diff will not detect were those changes came from).

You could try using


Option A

$ git log -p --no-merges --first-parent D'..M
  • -p gives you a diff (patch) for the commits listed
  • --no-merges will exclude merges from the list
  • --first-parent will only follow the first parent (the one you merged into eg private )
  • D'..M as explained in git revisision will

    Include commits that are reachable from <rev2> but exclude those that are reachable from <rev1>


Option B

A different approach would be to follow @torek's suggestion and create a temporary branch, cherry-pick all the commits onto it and then look at the diffs from this branch.

Because AFAIK git cherry-pick is not able to skip commits when specifying commit ranges you would first need to get a list of commits for cherry-picking (Here Option A is useful)

$ git log --no-merges --first-parent D'..M --pretty=format:%H
  • --pretty=format:%H will print all the commit hashes in long form

Create the temporal branch (which needs to have the correct starting point)

$ git checkout -b temp D'

And then cherry-pick those commits manually or try using this command (exchanged for a better command suggested by @torek)

$ git cherry-pick $(git rev-list --reverse --topo-order --no-merges --first-parent D'..M)
  • --reverse is used to reverse the order of commits printed (oldest to newest instead of the other way around)
  • --topo-order this will avoid problems with commits that have weird or wrong timestamps
  • --no-merges skip merge commits
  • --first-parent follow the mainline branch (eg the branch the merges were merged into )

This approach might fail if commits are based on changes which were merged in

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM