summary refs log tree commit diff
path: root/bin/git-sync
blob: 9a41c5c82b175c41122ee36691c7974d20ad95fd (plain) (blame)
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
#!/bin/bash
set -eu
[ -n "${DEBUG:-}" ] && set -x

sync() {
	local this_branch="${1:?}"
	local base_branch=""
	local upstream=""

	# detect base branch (when git-new was used)
	[ -n "$base_branch" ] || base_branch=$(git symbolic-ref --short refs/baseof/"$this_branch" 2>/dev/null || :)

	# recursive
	[ -n "$base_branch" ] && sync "$base_branch" && git switch "$this_branch"

	# detect trunk via origin/HEAD
	[ -n "$base_branch" ] || base_branch=$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null || :)

	# fallback to base branch == current branch
	[ -n "$base_branch" ] || base_branch=$this_branch

	# resolve upstream
	if [[ "$base_branch" != "origin/"* ]]; then
		upstream=$(git rev-parse --abbrev-ref --symbolic-full-name "$base_branch"'@{u}')
	else
		upstream=origin
	fi

	echo "Syncing $this_branch with $base_branch from $upstream"

	[ -n "${base_branch:?}" ] || exit 1
	[ -n "${upstream:?}" ] || exit 1

	# fetch upstream
	git fetch ${upstream/\// }

	# check if base and upstream have diverged
	if ! git diff --quiet "$upstream" "$base_branch"; then
		git diff --stat "$upstream" "$base_branch"
	fi

	# rebase
	git rebase --interactive "$upstream" "$this_branch"
}

sync "$(git symbolic-ref --short HEAD)"