Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Figure out dependencies of a commit we try to cherry pick

Assume something like the following:

                            HEAD/master     
                             |
A<--B<--C<--D<--E<--F<--G<--J  
        ^
        official 

Where official is a branch.
I wanted to cherry-pick 2 commits to official branch e.g.E and J
Both these commits were fixes affecting the same 3 files.
When I did git cherry-pick E it went fine but when I did git cherry-pick J I got some conflicts.
Looking at the diffs I realized that I needed to also cherry pick commit F which did a change in two of those 3 files which change was basically a method definition change and J was done on top of that.
So it was easy to fix by just doing git cherry-pick F && git cherry-pick J
Question:
If I wasn't aware of the changes done in those files and commit F was a big commit changing many files: Is there another way to figure out on which commit a commit we are trying to cherry pick depends on without manually doing a git log on the file and going commit by commit?

like image 788
Jim Avatar asked Feb 07 '17 20:02

Jim


1 Answers

Is there another way to figure out on which commit a commit we are trying to cherry pick depends on without manually doing a git log on the file and going commit by commit?

Yes there is - I wrote git-deps to automate precisely that task. Since it currently accepts a range of commits to analyse, in the case of your example you would need to pass it a singleton range containing just commit J, and also tell it to exclude any dependencies which are already in official:

git deps --exclude-commits official J^!

Behind the scenes the tool will then look at the diff of J^ with J, and then run git blame on any lines which are removed or modified, plus a configurable number of lines of surrounding context. This would result in it discovering that one or more of the lines J removes or modifies come from commit F, therefore it would output the SHA1 of commit F.

git-deps can not only discover dependencies of a single commit or range of commits, but also recurse a whole dependency tree. Therefore the entire cherry-picking scenario you describe could be automated into a single command:

git deps --recurse --exclude-commits official J^! | \ 
    tsort | \ 
    tac | \ 
    xargs -t git cherry-pick

Please note that this only guarantees that the cherry-picks will all cleanly apply, not that they are semantically correct. So the resulting branch head will still need to be carefully inspected and tested for correctness.

More convenient porting of commits between branches is the most obvious (but not the only) use case of git-deps, and for this reason I have dedicated a section of the README specifically to this use case. It even includes a YouTube video showing you exactly how to use it.

If you would like more details, you may be interested in a couple of talks I have presented on this and other related tools:

  • a talk given to the Git London User Group
  • a talk given at an OpenStack developer conference

I also spoke about the tool in episode #32 of the GitMinutes podcast.

like image 121
Adam Spiers Avatar answered Sep 23 '22 18:09

Adam Spiers