-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgithub-make-pr-branch
executable file
·203 lines (182 loc) · 7.81 KB
/
github-make-pr-branch
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
#!/usr/bin/env bash
# for usage and functionality information run this program w/o arguments
me=$(basename "$0")
if [[ "$#" -ne 5 ]]; then
echo "This program will checkout a forked version of the original repository, sync it with the original, create a new branch and set it up for a PR."
echo ""
echo "usage:"
echo ""
echo "$me auth user repo_user repo_name branch_name"
echo ""
echo "parameters:"
echo ""
echo " auth: ssh or https (ssh if your github account is setup to use ssh)"
echo " user: your github username"
echo " repo_user: repository to fork/use username"
echo " repo_name: repository to fork/use name"
echo " branch_name: name of the branch to create"
echo ""
echo "example: to make pr branch from https://github.com/stas00/ipyexperiments"
echo ""
echo "$me ssh my-github-username stas00 ipyexperiments new-feature-branch"
echo ""
echo "notes:"
echo ""
echo "- if the original repository has been already forked, it'll be done by the program (it will ask you for your github password)"
echo "- if the program is run from a directory that already contains a checked out git repository that matches the parameters, it will re-use it instead of making a new checkout."
echo "- if the requested branch already exists it'll reuse it"
echo "- if the fork master is out of sync with the original master it'll sync it first"
echo ""
exit 0
fi
auth="$1"
fork_user="$2"
repo_user="$3"
repo_name="$4"
new_branch_name="$5"
path="$repo_name-$new_branch_name"
# abort the script on any failure
set -e
# check curl is available
function check_curl_is_available {
command -v curl >/dev/null 2>&1 || { echo >&2 "$me requires 'curl' but it's not installed. Aborting."; exit 1; }
}
cmd="curl -s https://api.github.com/repos/${repo_user}/${repo_name} | jq --raw-output .default_branch"
default_branch=$(eval "$cmd") || exit 1
echo -e "\n\n*** Discovered default branch: $default_branch"
function run() {
local cmd="$@"
echo "running: $cmd"
eval $cmd || exit 1
}
function default_branch_sync() {
run "git fetch upstream"
run "git checkout ${default_branch}"
# XXX: this will fail if the user was committing directly to their forked `default_branch` branch
cmd="git merge --no-edit upstream/${default_branch}"
echo "running: $cmd"
eval $cmd || { git merge --abort; echo -e >&2 "\nError: $fork_user/$repo_name/${default_branch} can't be merged with repo_user/$repo_name/${default_branch}.\nYou must merge manually, or reset $fork_user/$repo_name/${default_branch}.\nAborting."; exit 1; }
run "git push"
# # XXX: here is how to reset the default_branch branch of the fork
# git remote add upstream git@github.com:$repo_user/$repo_name.git
# git fetch upstream
# git update-ref refs/heads/${default_branch} refs/remotes/upstream/${default_branch}
# git checkout ${default_branch}
# git stash
# git reset --hard upstream/${default_branch}
# git push origin ${default_branch} --force
}
if [[ "$auth" == "ssh" ]]; then
prefix="git@github.com:"
else
prefix="https://github.com/"
fi
url="$prefix$fork_user/$repo_name.git"
# fork the repo if it hasn't been forked yet
echo -e "\n\n*** Checking if we need to fork"
was_already_forked=0
repo_name_already_exists=0
git ls-remote $url >/dev/null 2>&1 && repo_name_already_exists=1
if [[ "$repo_name_already_exists" -eq 1 ]]; then
echo "$url already exists, checking for collision"
# the last html_url is the one of the fork origin (there are 6 of those in the response)
cmd="curl -s https://api.github.com/repos/$fork_user/$repo_name | grep html_url | tail -1"
echo $cmd
out=$(eval "$cmd") || exit 1
if [[ $out != *"$repo_user/$repo_name"* ]]; then
echo "Detected collision: there already exists a forked repo with the same name but originating from"
echo "$out"
echo "Either rename that pre-existing repo in github and then use this tool, or do the PR setup manually"
exit 1
else
was_already_forked=1
echo "$url is already forked"
fi
else
echo "$url doesn't exist - need to fork"
check_curl_is_available
cmd="curl -X POST -u $fork_user https://api.github.com/repos/$repo_user/$repo_name/forks"
echo $cmd
out=$(eval "$cmd") || exit 1
#echo "got $out"
if [[ $out != *"full_name"* ]]; then
echo "failed to fork: $out"
exit 1
fi
echo "sleeping 10 sec to allow github to complete the fork"
sleep 10
fi
# support an already existing checkout if it matches the desired parameters, but only if it's not dirty
clone_is_needed=1
if [[ -e ".git" ]]; then
echo "detected current dir to be a git repository"
if [[ -n "$(git status -s)" ]]; then
echo "git status is not clean, not going to re-use the current checkout"
clone_is_needed=1
else
cur_url=$(git config --get remote.origin.url)
if [[ "$cur_url" == "$url" ]]; then
echo "already on the right repo, going to re-use the current checkout"
clone_is_needed=0
fi
fi
fi
# clone
if [[ "$clone_is_needed" -eq 1 ]]; then
echo -e "\n\n*** Cloning $url to $path"
run "git clone $url $path"
run "cd $path"
fi
# setup this fork to track the upstream
echo -e "\n\n*** Setting up this fork to track the upstream"
orig_repo_url="$prefix$repo_user/$repo_name.git"
run "git remote add upstream $orig_repo_url || echo 'already exists'"
# show the setup
run "git remote -v"
# let's sync the forked repo default_branch with the upstream default_branch if it hasn't been just forked
if [[ "$was_already_forked" -eq 1 ]]; then
echo -e "\n\n*** Syncing $fork_user/${default_branch} with $repo_user/${default_branch}"
default_branch_sync
echo "Done"
fi
# now create a branch
echo -e "\n\n*** Creating '$new_branch_name' branch and setting its upstream for an easy push"
branch_already_exists=0
git show-branch $new_branch_name >/dev/null 2>&1 && branch_already_exists=1
if [[ "$branch_already_exists" -eq 1 ]]; then
echo "$new_branch_name already exists, switching to it"
run "git checkout $new_branch_name"
else
echo "$new_branch_name doesn't yet exist, creating"
run "git checkout -b $new_branch_name"
echo -e "'$new_branch_name' branch was successfully created"
fi
# set this branch's upstream, so to enable `git push` and other git
# commands without needing to pass any more arguments.
echo -e "\n\n*** Set '$new_branch_name' branch's upstream to simplify push and alikes"
run "git push --set-upstream origin $new_branch_name"
echo -e "\n\n### Successfully created branch '$new_branch_name' ###\n\n"
# give parting instructions
echo -e "\n\n*** Next do: \n"
# only suggest to chdir if we made a clone
echo -e "1. Switch to the working dir:\n"
if [[ "$clone_is_needed" -eq 1 ]]; then
echo -e "cd $path\n"
else
echo -e "cd .\n"
fi
echo -e "2. Validate you're on the right repo/branch:\n"
echo -e "echo on repo: \$(git config --get remote.origin.url | sed 's|^.*//||; s/.*@//; s/[^:/]\+[:/]//; s/.git$//') branch: \$(git branch | sed -n '/\* /s///p')\n"
echo -e "3. And do your work.\n"
echo -e "4. When you're done:\n"
echo -e "git add <newfiles> # if you added new files"
echo -e "git commit -a # if you want to commit all modified/added files"
echo -e "git push # push files into $new_branch_name branch\n"
echo -e "5. Then go to:\n"
echo -e " https://github.com/$fork_user/$repo_name/tree/$new_branch_name\n"
echo -e "review your changes and when you're happy with what you see, submit your PR.\n"
echo "While it's very good to review your PR on github before submitting it, if you want to use a CLI solution, there are several solutions to choose from:"
echo "* https://github.com/github/hub"
echo "* https://github.com/jd/git-pull-request"
echo "* https://github.com/jehiah/git-open-pull"
echo "* https://www.npmjs.com/package/pullr"