-
Notifications
You must be signed in to change notification settings - Fork 0
/
git-show-merged-branches
executable file
·109 lines (95 loc) · 3.87 KB
/
git-show-merged-branches
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/usr/bin/env bash
#
# Copyright (c) 2020 Dan Kalowsky <[email protected]>. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
function _display_help {
echo ""
echo "==============================================================================="
echo "Show locally merged branches: "
echo -e "\tThis command takes one additional argument to automatically delete the "
echo -e "\tmerged branches for you. By default the command will skip the default "
echo -e "\tbranch, release, and the currently selected branches. "
echo " "
echo "Options: "
echo -e "\t-d Adding -d will automatically remove branches discovered to be merged. "
echo -e "\t This will skip the default and release branches. "
echo "==============================================================================="
echo ""
}
function _old_merge_check() {
#
# Now comes the more challenging... building a list of Squash and Merged branches
# This seems to fail when the branch is rebased on the GitLab and GitHub service
# and then merged in.
#
local merge_base=
local dangling_commit=
while read -r branch; do
if [[ "${merged_local_branches[*]}" =~ ${branch} ]]; then
#echo "DEBUG: Already found: skipping ${branch}"
continue
fi
merge_base=$(git merge-base "origin/${DEFAULT_BRANCH}" -- "${branch}")
tree=$(git rev-parse "${branch}"^{tree})
# okay now create a temporary squash commit
dangling_commit=$(git commit-tree "${tree}" -p "${merge_base}" -m _)
# now check if the dangling commit has been squashed to master
# this works because the next commit should be based upon the predictable history of master
if [[ $(git cherry "origin/${DEFAULT_BRANCH}" "${dangling_commit}") == "-"* ]]; then
merged_local_branches=( "${branch}" "${merged_local_branches[@]}" )
#echo "DEBUG: found squashed branch ${branch}"
fi
done < <(git branch --no-color | grep -v -E "(\*|${DEFAULT_BRANCH}*|release*)" | cut -f2 -d $'\t')
}
function _new_merge_check() {
#
# This seems to work better for branches that have been rebased on GitLab
# or GitHub and then merged in. Not sure if it is completely correct yet.
#
while read -r branch; do
if [[ "${merged_local_branches[*]}" =~ ${branch} ]]; then
#echo "DEBUG: Already found: skipping ${branch}"
continue
fi
git merge-base --is-ancestor "${branch}" origin/"${DEFAULT_BRANCH}"
if [ "$?" -eq 0 ]; then
merged_local_branches=( "${branch}" "${merged_local_branches[@]}" )
fi
done < <(git branch --no-color | grep -v -E "(\*|${DEFAULT_BRANCH}*|release*)" | cut -f2 -d $'\t')
}
action="Merged"
#
# It isn't a good practice to just assume the default branch is named master. Use git to tell
# what is the default branch in use for that specific repo, and use that value instead.
#
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@')
if [ "$#" -eq 1 ]; then
if [ "$1" == "-h" ]; then
_display_help
exit 0
fi
if [ "$1" == "-d" ]; then
action="Deleting"
fi
if [ "$1" == "-x" ]; then
set -o xtrace
export PS4='+ ${BASH_SOURCE:-}:${FUNCNAME[0]:-}:L${LINENO:-}: '
fi
fi
#
# Build the list of traditionally merged branches
#
merged_local_branches=( $(git branch --no-color --merged ${DEFAULT_BRANCH} | grep -v -E "(\*|${DEFAULT_BRANCH}*|release*)" | cut -f2 -d $'\t' ) )
#_old_merge_check
_new_merge_check
#
# Now that we have our list, let's go display it and clean it out if so desired
#
for branch in "${merged_local_branches[@]}"; do
echo "${action} : ${branch}"
if [ "${action}" == "Deleting" ]; then
git branch -D -- "${branch}" &>/dev/null
fi
done