-
Notifications
You must be signed in to change notification settings - Fork 0
/
git-submodule-details
executable file
·76 lines (68 loc) · 3.3 KB
/
git-submodule-details
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
#!/bin/bash
_strong="\033[1;97m"
_red="\033[31m"
_reset="\033[0m"
# Note: using `while read` gives us support for spaces in dir names.
# Mention uninitialized submodules first.
git submodule | grep "^-" | cut -c43- | while read -r module; do
echo -e "Submodule ${_strong}$module${_reset} not initialized/loaded."
done
# Iterate over initialized submodules.
git submodule foreach 'echo $sm_path' | grep -v '^Entering' | while read -r module; do
# Gather information about actual and recorded submodule status.
current_commit=$(cd "$module"; git rev-parse HEAD)
# Note: `git ls-tree` mixes tabs and spaces for separating columns, but awk handles this.
recorded_commit=$(git ls-tree HEAD -- "$module" | awk '{print $3}')
if [ -e ".git/MERGE_HEAD" ]; then
merged_commit=$(git ls-tree MERGE_HEAD -- "$module" | awk '{print $3}')
elif [ -e ".git/rebase-merge" ]; then
rebased_commit=$(git ls-tree REBASE_HEAD -- "$module" | awk '{print $3}')
base_commit=$(git ls-tree $(cat .git/rebase-merge/onto) -- "$module" | awk '{print $3}')
fi
# Show heading with summary information.
diff_summary=$(git diff --submodule=log HEAD -- $module | grep "^Submodule")
sm_status=$(git submodule status -- "$module" | cut -c1-10)
[ $sm_status = "U000000000" ] && diff_summary="Submodule $module (CONFLICT):"
summary=${diff_summary:-Submodule $module (unchanged):}
echo -e $(echo "\n$summary" | sed "s/$module/\\${_strong}$module\\${_reset}/")
cd "$module"
# newly added submodule (not committed in superproject yet)
if [ -z $recorded_commit ]; then
git log --oneline --no-decorate HEAD -5
echo "(...)"
# check that requested commit is actually present in submodule
elif ! git rev-list $recorded_commit &> /dev/null; then
echo "Superproject wants the submodule to be at commit $recorded_commit"
echo -e "but this ${_red}commit is not present${_reset} in submodule database."
# superproject merge in progress
elif [ -n "$merged_commit" ]; then
git tag OURS_HEAD $recorded_commit
git tag THEIRS_HEAD $merged_commit
git divergence HEAD $recorded_commit $merged_commit
git tag -d OURS_HEAD >/dev/null
git tag -d THEIRS_HEAD >/dev/null
# superproject rebase in progress
elif [ -e "$rebased_commit" ]; then
git tag REBASED_HEAD $rebased_commit
git tag TARGET_HEAD $base_commit
git divergence HEAD $rebased_commit $base_commit
git tag -d REBASED_HEAD TARGET_HEAD >/dev/null
# just show recorded commit if it hasn't changed
elif [ $recorded_commit = $current_commit ]; then
git log --oneline --no-decorate -1 HEAD
# if there are changed files in submodule
[[ $summary =~ "contains modified content" ]] && git status --short
# different commit checked out in submodule
else
git tag SUPERPROJECT_HEAD $recorded_commit
git divergence $recorded_commit HEAD
git tag -d SUPERPROJECT_HEAD >/dev/null
fi
mainline=$(git rev-parse --abbrev-ref --verify origin/HEAD 2>/dev/null)
if [ -n "$mainline" ]; then
behind_count=$(git rev-list --count ..$mainline)
ahead_count=$(git rev-list --count $mainline..)
echo $ahead_count commits ahead, $behind_count commits behind $mainline.
fi
cd ..
done