Skip to content

Commit 85e7543

Browse files
authored
Merge pull request jianli#11 from brewingcode/master
pass in optional branch name after commit sha
2 parents 3206416 + 87b1410 commit 85e7543

File tree

2 files changed

+72
-18
lines changed

2 files changed

+72
-18
lines changed

README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
**git get-merge** is a `git` command to locate the merge that introduced a given commit into your repository's master branch. It is correct with very high probability.
1+
**git get-merge** is a `git` command to locate the merge that introduced a
2+
given commit into a given branch in your repository (`master` by default). It
3+
is correct with very high probability.
24

35
## Installation
46

@@ -20,3 +22,36 @@ Date: Fri Jul 4 02:01:40 2014 +0200
2022
Update setup.py
2123

2224
```
25+
26+
## More Info
27+
28+
```sh
29+
> git get-merge help
30+
usage: git get-merge <sha> [branch]
31+
32+
Attempt to find when commit <sha> was merged to <branch>, where <branch> is
33+
`master` by default. Two methods are used:
34+
35+
# method 1
36+
37+
Stupid algorithm which works most of the time.
38+
39+
Follow the commit downstream and return the first merge into another
40+
branch, as opposed to a merge from another branch. Hopefully, this other
41+
branch is <branch>.
42+
43+
Abort if the graph starts branching or terminates.
44+
45+
46+
# method 2
47+
48+
Find the earliest common commit between ancestry-path and first-parent.
49+
50+
Source: http://stackoverflow.com/a/8492711
51+
52+
This is the correct algorithm assuming a properly-maintained git
53+
history. However, if there has ever been a fast-forward merge of a feature
54+
branch into <branch>, the first-parent history of <branch> will have been
55+
tampered with and this "correct" approach could fail.
56+
```
57+

get_merge/__init__.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,36 @@
33
import sys
44

55

6-
def validate(repo, parent):
7-
master_commits = repo.git.rev_list('master').split()
8-
if parent not in set(master_commits):
6+
def validate(repo, parent, branch):
7+
branch_commits = repo.git.rev_list(branch).split()
8+
if parent not in set(branch_commits):
99
raise ValueError(
10-
'This commit has not actually been merged into master.')
10+
'This commit has not actually been merged into %s' % branch)
1111

1212
first_parent = repo.git.rev_list(
13-
'master', first_parent=True).split()
13+
branch, first_parent=True).split()
1414
if parent in set(first_parent):
1515
raise ValueError(
16-
'This commit was originally made on the master branch?')
16+
'This commit was originally made on the %s branch?' % branch)
1717

1818

19-
def get_first_merge_into(repo, parent):
19+
def get_first_merge_into(repo, parent, branch):
2020
"""
2121
Stupid algorithm which works most of the time.
2222
2323
Follow the commit downstream and return the first merge into another
2424
branch, as opposed to a merge from another branch. Hopefully, this other
25-
branch is master.
25+
branch is <branch>.
2626
2727
Abort if the graph starts branching or terminates.
2828
"""
2929
children_dict = {}
30-
for line in repo.git.rev_list('master', children=True).split('\n'):
30+
for line in repo.git.rev_list(branch, children=True).split('\n'):
3131
commits = line.split()
3232
children_dict[commits[0]] = commits[1:]
3333

3434
parents_dict = {}
35-
for line in repo.git.rev_list('master', parents=True).split('\n'):
35+
for line in repo.git.rev_list(branch, parents=True).split('\n'):
3636
commits = line.split()
3737
parents_dict[commits[0]] = commits[1:]
3838

@@ -51,21 +51,21 @@ def is_second_parent(child, parent):
5151
parent = child
5252

5353

54-
def get_ancestry_path_first_parent_match(repo, parent):
54+
def get_ancestry_path_first_parent_match(repo, parent, branch):
5555
"""
5656
Find the earliest common commit between ancestry-path and first-parent.
5757
5858
Source: http://stackoverflow.com/a/8492711
5959
6060
This is the correct algorithm assuming a properly-maintained git
6161
history. However, if there has ever been a fast-forward merge of a feature
62-
branch into master, the first-parent history of master will have been
62+
branch into <branch>, the first-parent history of <branch> will have been
6363
tampered with and this "correct" approach could fail.
6464
"""
6565
ancestry_path = repo.git.rev_list(
66-
parent + '..master', ancestry_path=True).split()
66+
parent + '..' + branch, ancestry_path=True).split()
6767
first_parent = repo.git.rev_list(
68-
'master', first_parent=True).split()
68+
branch, first_parent=True).split()
6969

7070
for commit in reversed(ancestry_path):
7171
if commit in first_parent:
@@ -74,8 +74,27 @@ def get_ancestry_path_first_parent_match(repo, parent):
7474

7575

7676
def get_merge():
77+
if 'help' in sys.argv:
78+
print("""usage: git get-merge <sha> [branch]
79+
80+
Attempt to find when commit <sha> was merged to <branch>, where <branch> is
81+
`master` by default. Two methods are used:
82+
83+
# method 1
84+
%s
85+
86+
# method 2
87+
%s
88+
""" % (get_first_merge_into.__doc__, get_ancestry_path_first_parent_match.__doc__))
89+
return 0
90+
7791
repo = git.Repo(os.getcwd())
7892

93+
try:
94+
branch = sys.argv[2]
95+
except IndexError:
96+
branch = 'master'
97+
7998
try:
8099
parent = repo.git.rev_parse(sys.argv[1])
81100
repo.git.show(sys.argv[1]) # validate existence
@@ -84,13 +103,13 @@ def get_merge():
84103
return 1
85104

86105
try:
87-
validate(repo, parent)
106+
validate(repo, parent, branch)
88107
except ValueError as err:
89108
print('\n'.join(err.args))
90109
return 1
91110

92-
guess1 = get_first_merge_into(repo, parent)
93-
guess2 = get_ancestry_path_first_parent_match(repo, parent)
111+
guess1 = get_first_merge_into(repo, parent, branch)
112+
guess2 = get_ancestry_path_first_parent_match(repo, parent, branch)
94113
if not (guess1 or guess2):
95114
print('Unable to resolve.')
96115
return 1

0 commit comments

Comments
 (0)