I’ve been wanting to generate commands and menu items for some basic form of GitHub integration for Sublime Merge for a while now, finally completed it today (now with GitLab & Bitbucket support!).
The commands and menu items are implemented using a git alias which also allows command line usage if wanted:
- open the repo:
git open repo
- open the current branch:
git open branch
- open the current commit:
git open commit
- create a pr on the current branch:
git open pr
Each command supports an extra argument for specification:
- open a specific branch:
git open branch $specific_branch
- open a specific commit:
git open commit $specific_commit
- create a pr on a specific branch:
git open pr $specific_branch
- open a specific tag:
git open tag $specific_tag
Notes/Caveats:
- the alias only works by default on macOS, changing the
open
command in the last line of step 1 (open "$repo_url"
) to a supported command by your OS is needed- this link may help: https://dwheeler.com/essays/open-files-urls.html
- all commands/menu items are always enabled even for non-remote repositories, this is can be fixed once plugins are supported in SM
- when using the command line there is no commit/tag validation, but GitHub/GitLab/Bitbucket will show an error if so
- for commits & tags, only one remote is supported & uses
origin
-
add this git alias:
git config --global alias.open '!f() { local type="${1:-branch}" local target="${2:-HEAD}" local remote="origin" if [ "$type" = "branch" -o "$type" = "pr" ]; then # get full name (i.e. refs/heads/*; refs/remotes/*/*); src: https://stackoverflow.com/a/9753364 target="$(git rev-parse --symbolic-full-name "$target")" if [ "$target" != "${target#"refs/remotes/"}" ]; then # extract from remote branch reference target="${target#"refs/remotes/"}" else # extract from local branch reference; src: https://stackoverflow.com/a/9753364 target="$(git for-each-ref --format="%(upstream:short)" "$target")" fi # split remote/branch remote="${target%%/*}" target="${target#"$remote/"}" if [ -z "$remote" ]; then echo "Branch ($2) does not point to a remote repository." >&2 return 2 fi fi local repo_url="$(git remote get-url "$remote" | sed -E -e "s/(\.(com|org|io))\:/\1\//" -e "s/git@/https:\/\//" -e "s/\.git$//")" if [ -z "$repo_url" ]; then echo "Cannot open: no remote repository configured under (origin)" >&2 return 1 fi case "$(tr "[:upper:]" "[:lower:]" <<< "$repo_url")" in *github*) [ "$type" = "commit" ] && repo_url="$repo_url/commit/$(git rev-parse "$target")" [ "$type" = "pr" ] && repo_url="$repo_url/compare/$target?expand=1" [ "$type" = "tag" ] && repo_url="$repo_url/releases/tag/$target" [ "$type" = "branch" ] && repo_url="$repo_url/tree/$target" ;; *bitbucket*) [ "$type" = "commit" ] && repo_url="$repo_url/commits/$(git rev-parse "$target")" [ "$type" = "pr" ] && repo_url="$repo_url/pull-requests/new?source=$target" [ "$type" = "tag" ] && repo_url="$repo_url/src/$target" [ "$type" = "branch" ] && repo_url="$repo_url/src/$target" ;; *gitlab*) [ "$type" = "commit" ] && repo_url="$repo_url/-/commit/$(git rev-parse "$target")" [ "$type" = "pr" ] && repo_url="$repo_url/-/merge_requests/new?merge_request[source_branch]=$target" [ "$type" = "tag" ] && repo_url="$repo_url/-/tags/$target" [ "$type" = "branch" ] && repo_url="$repo_url/-/tree/$target" ;; *) echo "Cannot open: not a GitHub, GitLab, or Bitbucket repository" >&2 return 1 ;; esac open "$repo_url" }; f'
-
add these commands to
Default.sublime-commands
:[ { "caption": "Open Repository in GitHub/GitLab/Bitbucket", "command": "git", "args": { "argv": ["open", "repo"] } }, { "caption": "Open Branch in GitHub/GitLab/Bitbucket…", "command": "git", "args": { "argv": ["open", "branch", "$select_branch"] } }, { "caption": "Create Pull Request in GitHub/GitLab/Bitbucket…", "command": "git", "args": { "argv": ["open", "pr", "$select_branch"] } }, { "caption": "Open Tag in GitHub/GitLab/Bitbucket…", "command": "git", "args": { "argv": ["open", "tag", "$select_tag"] } } ]
-
add these menu items to
Branch.sublime-menu
:[ { "caption": "-", "id": "end" }, { "caption": "Open Branch $branch in GitHub/GitLab/Bitbucket", "command": "git", "args": { "argv": ["open", "branch", "$branch"] } }, { "caption": "Create Pull Request on $branch in GitHub/GitLab/Bitbucket", "command": "git", "args": { "argv": ["open", "pr", "$branch"] } } ]
-
add these menu items to
Remote Branch.sublime-menu
:[ { "caption": "-", "id": "end" }, { "caption": "Open Branch $branch in GitHub/GitLab/Bitbucket", "command": "git", "args": { "argv": ["open", "branch", "$branch"] } }, { "caption": "Create Pull Request on $branch in GitHub/GitLab/Bitbucket", "command": "git", "args": { "argv": ["open", "pr", "$branch"] } } ]
-
add this menu item to
Commit.sublime-menu
:[ { "caption": "Open Commit $short_commit in GitHub/GitLab/Bitbucket", "command": "git", "args": { "argv": ["open", "commit", "$commit"] } } ]
-
add this menu item to
Tag.sublime-menu
:[ { "caption": "Open Tag $tag_name in GitHub/GitLab/Bitbucket", "command": "git", "args": { "argv": ["open", "tag", "$tag_name"] } } ]