Cherry-Picking of Code Commits in Long-Running, Multi-release Software

Panuchart Bunyakiati and Chadarat Phipathananunth

This paper presents Tartarian, a tool that supports maintenance of software with long-running, multi-release branches in distributed version control systems. When new maintenance code, such as bug fixes and code improvement, is committed into a branch, it is likely that such code can be applied or reused with some other branches. To do so, a developer may manually identify a commit and cherry pick it. Tartarian can support this activity by providing commit hashtags, which the developer uses as metadata to specify their intentions when committing the code. With these tags, Tartarian uses dependency graph, that represents the dependency constraints of the branches, and Branch Identifier, which matches the commit hashtags with the dependency graph, to identify the applicable branches for the commits. Using Tartarian, developers may be able to maintain software with multiple releases more efficiently.

A presentation of Tartarian is available here.

Describing Cherry-Picking

Starting with describing the Cherry-picking process using DAG of a repository having three releases 1.1, 1.2 and 1.3 where release 1.1 has commit a, release 1.2 has commits a, b and c and release 1.3 has commits a, b, c, d and e. Once the bug fix f is committed to release 1.3, it can be cherry picked to release 1.1 and 1.2 hence release 1.1 becomes a and f, release 1.2 becomes a, b, c and f and release 1.3 becomes a, b, c, d, e and f.

Cherry-picking applies a commit f in branch 1.3 to other branches 1.1 and 1.2.

* b44ea88 (1.2) Added f (cherry picked from db55fd2)
| * 4fcd797 (1.1) Added f (cherry picked from db55fd2)
| | * db55fd2 (HEAD -> master, 1.3) Added f
| | * 3e63476 Added e
| | * f0a729e Added d
| |/
|/|
* | 9981679 Added c
* | 01ea7e6 Added b
|/
* 5597940 Added a
Commit f is cherry picked from 1.3 to 1.1 and 1.2.

Introducing Running Example

As our running example describes the dependencies of Jetty 9.2.x. 9.3.x and 9.4.x release branches, one of which being the dependencies on JDK1.7 (for Jetty 9.2.x) and JDK1.8 (for Jetty 9.3.x and 9.4.x).

Jetty 9.2.x depends on JDK 1.7, Jetty 9.3.x and 9.4.x depend on JDK 1.8 * a419765 (HEAD -> 9.4.x, master)
* d3731d0 (9.3.x)
* cc6769f (9.2.x)
The DAG of the release 9.2.x, 9.3.x and 9.4.x.

Committing to a branch

Next, we will demonstrate a developer committing to release 9.4.x. The commit x makes changes to the code that depends on JDK1.8. For example, the changes in APIs from using the old method \emph{m.getParameterTypes().length} to using a more efficient method introduced in JDK1.8, m.getParameterCount(). This will affect all release branches depending on JDK1.8.

x is committed to release 9.4.x.

* c8836e1 (HEAD -> 9.4.x) changed deprecated method
* a419765 (master)
* d3731d0 (9.3.x)
* cc6769f (9.2.x)
x is committed to release 9.4.x as commit c8836e1.

Without Tartarian

Without Tartarian, a developer must manually identify the commits that are applicable for code reuse and make a cherry-picking commit. He usually browses through the issues, related commits and the diff between the versions. Then, he makes decision whether to cherry pick and should the commit can be used as-is or must be modified.

x is manually cherry picked to 9.3.x

$ git cherry-pick c8836e1
[9.3.x 740dbfa] changed deprecated method
Date: Wed Jun 7 18:57:27 2017 +0700
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 x
$
x is manually cherry picked to 9.3.x as commit 740dbfa.

With Tartarian

With Tartarian, developers use hashtag as metadata such as #deprecated to indicate the purpose of this commit and its dependency which effect other release branches. $git tcommit -m "changed deprecated method 132215 #deprecated{JDK, 1.8+}"

Commit x is tagged with #deprecated{JDK,1.8+}

* c8836e1 (HEAD -> 9.4.x) changed deprecated method x #deprecated{JDK,1.8+}
* a419765 (master)
* d3731d0 (9.3.x)
* cc6769f (9.2.x)
A commit message of x with the #deprecated{JDK,1.8}.

Identifying the affected release branches

Tartarian uses hast tags as constraints on the dependency graph to identify the affected release branches. After a code change is committed to the repository, the Branch Identifier searches through the graph to identify the affected releases. Developers can read the recommendation Tartarian made by using: $git tcommit -r

Tartarian recommends cherry-picking x to branch 9.3.x

* c8836e1 (9.4.x) change deprecated method
* a419765 (master)
* d3731d0 (HEAD -> 9.3.x)
* cc6769f (9.2.x)
$ git tcommit -r
[9.4.x c8836e1] change deprecated method
Date: Wed Jun 7 18:55:17 2017 +0700
Priority: Low
c8836e1 is applicable to branch 9.3.x because
it is likely to depend on JDK1.8
$
Developers use git tcommit -r to read the recommendation Tartarian made.

Making decision to cherry pick

With this recommendation, developers can make informed decision about the potential commits to be cherry picked and can reuse code more efficiently.

x is cherry picked to 9.3.x

* 740dbfa (HEAD -> 9.3.x) cherry picked from c8836e1
| * c8836e1 (9.4.x) changed deprecated method
| * a419765 (master)
|/
* d3731d0
* cc6769f (9.2.x)
x is cherry picked to 9.3.x as shown in the DAG as commit 740dbfa.