[depot_tools] Add --fork-point when computing merge-base

Using --fork-point when possible reduces the number of merge conflicts when running merge-base.

Bug: 1111269
Change-Id: I7240fdc9a613d2eb4e856b5677fc713551d7afe9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2519729
Reviewed-by: Josip Sokcevic <sokcevic@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
diff --git a/git_common.py b/git_common.py
index 91ddeb4..e9b3220 100644
--- a/git_common.py
+++ b/git_common.py
@@ -530,7 +530,11 @@
   parent = parent or upstream(branch)
   if parent is None or branch is None:
     return None
-  actual_merge_base = run('merge-base', parent, branch)
+
+  try:
+    actual_merge_base = run('merge-base', '--fork-point', parent, branch)
+  except subprocess2.CalledProcessError:
+    actual_merge_base = run('merge-base', parent, branch)
 
   if base_upstream != parent:
     base = None
diff --git a/tests/git_common_test.py b/tests/git_common_test.py
index c382cdb..e6e2f83 100755
--- a/tests/git_common_test.py
+++ b/tests/git_common_test.py
@@ -692,6 +692,36 @@
     self.assertIsNone(
       self.repo.run(self.gc.get_or_create_merge_base, 'branch_DOG'))
 
+  def testMergeBaseWithForkPoint(self):
+    self.repo.git('commit', '--allow-empty', '-am', 'foooooo')
+    self.repo.git('checkout','-tb', 'foobarA', 'master')
+    foobarA = self.repo.run(self.gc.hash_one, 'foobarA', short=True)
+
+    self.repo.git('checkout','-tb', 'foobarB', 'foobarA')
+    with self.repo.open('cl1', 'w') as f:
+        f.write('cl1')
+    self.repo.git('add', 'cl1')
+    self.repo.git_commit('cl1')
+    foobarB_old = self.repo.run(self.gc.hash_one, 'foobarB', short=True)
+
+    self.repo.git('checkout','-tb', 'foobarC', 'foobarB')
+    with self.repo.open('cl2', 'w') as f:
+        f.write('cl2')
+    self.repo.git('add', 'cl2')
+    self.repo.git_commit('cl2')
+    foobarC = self.repo.run(self.gc.hash_one, 'foobarC', short=True)
+
+    self.repo.git('checkout', 'foobarB')
+    with self.repo.open('cl1', 'w') as f:
+      f.write('amend cl1')
+    self.repo.git('add', 'cl1')
+    self.repo.git('commit', '--amend', '-m', 'amend cl1')
+
+    self.assertIn(foobarA,
+      self.repo.run(self.gc.get_or_create_merge_base, 'foobarB', foobarB_old))
+    self.assertIn(foobarB_old,
+      self.repo.run(self.gc.get_or_create_merge_base, foobarC, 'foobarB'))
+
   def testGetBranchTree(self):
     skipped, tree = self.repo.run(self.gc.get_branch_tree)
     # This check fails with git 2.4 (see crbug.com/487172)