-
Notifications
You must be signed in to change notification settings - Fork 30
/
git.zsh
299 lines (269 loc) · 9.14 KB
/
git.zsh
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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
######################################################################
# ZSH aliases and helper functions for working with Git #
# #
# Licensed under MIT (C) Alicia Sykes 2022 <https://aliciasykes.com> #
######################################################################
# Basics
alias g="git"
alias gs="git status" # List changed files
alias ga="git add" # Add <files> to the next commit
alias gaa="git add ." # Add all changed files
alias grm="git rm" # Remove <file>
alias gc="git commit" # Commit staged files, needs -m ""
alias gps="git push" # Push local commits to <origin> <branch>
alias gpl="git pull" # Pull changes with <origin> <branch>
alias gf="git fetch" # Download branch changes, without modifying files
# Merging and Rebasing
alias grb="git rebase" # Rebase the current HEAD into <branch>
alias grba="git rebase --abort" # Cancel current rebase sesh
alias grbc="git rebase --continue" # Continue onto next diff
alias gm="git merge" # Merge <branch> into your current HEAD
# Repo setup
alias gi="git init" # Initiialize a new empty local repo
alias gcl="git clone" # Downloads repo from <url>
# Branching
alias gch="git checkout" # Switch the HEAD to <branch>
alias gb="git branch" # Create a new <branch> from HEAD
alias gd="git diff" # Show all changes to untracked files
alias gtree="git log --graph --oneline --decorate --abbrev-commit" # Show branch tree
alias gl='git log'
# Tags
alias gt="git tag" # Tag the current commit, 1 param
alias gtl="git tag -l" # List all tags, optionally with pattern
alias gtlm="git tag -n" # List all tags, with their messages
alias gtp="git push --tags" # Publish tags
# Origin
alias gr="git remote"
alias grs="git remote show" # Show current remote origin
alias grl="git remote -v" # List all currently configured remotes
alias grr="git remote rm origin" # Remove current origin
alias gra="git remote add" # Add new remote origin
alias grurl="git remote set-url origin" # Sets URL of existing origin
# Undoing
alias guc="git revert" # Revert a <commit>
alias gu="git reset" # Reset HEAD pointer to a <commit>, perserves changes
alias gua="git reset --hard HEAD" # Resets all uncommited changes
alias gnewmsg="git commit --amend -m" # Update <message> of previous commit
alias gclean="git clean -df" # Remove all untracked files
# Git LFS
alias glfsi='git lfs install'
alias glfst='git lfs track'
alias glfsls='git lfs ls-files'
alias glfsmi='git lfs migrate import --include='
# Push LFS changes to current branch
function gplfs() {
git lfs push origin "$(git_current_branch)" --all
}
alias gx='cd $(git rev-parse --show-toplevel)'
# Navigate back to project root (where .git is)
function jump-to-git-root {
local _root_dir="$(git rev-parse --show-toplevel 2>/dev/null)"
if [[ $? -gt 0 ]]; then
>&2 echo '\033[1;93m Not a Git repo\033[0m'
exit 1
fi
local _pwd=$(pwd)
if [[ $_pwd = $_root_dir ]]; then
# Handle submodules
_root_dir="$(git -C $(dirname $_pwd) rev-parse --show-toplevel 2>/dev/null)"
if [[ $? -gt 0 ]]; then
echo "\033[0;96m Already at Git repo root.\033[0m"
return 0
fi
fi
# Make `cd -` work.
OLDPWD=$_pwd
echo "\033[0;96m Git repo root: $_root_dir\033[0m"
cd $_root_dir
}
alias gj='jump-to-git-root'
# Shorthand clone (e.g. $ clone lissy93/dotfiles)
function clone {
default_service='github.com' # Used if full URL isn't specified
default_username='lissy93' # Used if repo org / username isn't specified
use_ssh=true # Use SSH instead of HTTPS
user_input=$1
target=${2:-''}
# Help flag passed, show manual and exit
if [[ $user_input == --help ]] || [[ $user_input == -h ]]; then
echo -e 'This will clone a git repo, and cd into it.';
echo -e 'Either specify repo name, oe user/repo, or a full URL.'
echo -e 'If no target directory is specified, the repo name will be used.'
echo -e 'E.g. `$ clone lissy93/dotfiles`'
return;
# No input specified, prompt user
elif [ $# -eq 0 ]; then
echo 'Enter a user/repo or full URL: ';
read user_input;
fi
# Determine input type, and make clone url
if [[ $user_input == git@* || $user_input == *://* ]]
then
# Full URL was provided
REPO_URL=$user_input;
elif [[ $user_input == */* ]]; then
# Username/repo was provided
if [ "$use_ssh" = true ] ; then
REPO_URL="git@$default_service:$user_input.git";
else
REPO_URL="https://$default_service/$user_input.git";
fi
else
# Just repo name was provided
if [ "$use_ssh" = true ] ; then
REPO_URL="git@$default_service:$default_username/$user_input.git";
else
REPO_URL="https://$default_service/$default_username/$user_input.git";
fi
fi
# Clone repo
git clone $REPO_URL $target;
# cd into newly cloned directory
cd "$(basename "$_" .git)"
# Print results
if test "$?" -eq 0; then
echo -e "☑️ \033[1;96mCloned $REPO_URL into $(pwd), and cd'd into it.\033[0m"
else
echo -e "❌ \033[1;91mFailed to clone $REPO_URL\033[0m"
fi
}
# Sync fork against upstream repo
function gsync {
# If no upstream origin provided, prompt user for it
if ! git remote -v | grep -q 'upstream'; then
echo 'Enter the upstream git url: ';
read url;
git remote add upstream "$url"
fi
git remote -v
git fetch upstream
git pull upstream master
git checkout master
git rebase upstream/master
}
# Make git commit with -m
function gcommit {
commit_msg=$@
if [ $# -eq 0 ]; then
echo 'Enter a commit message';
read commit_msg;
fi
git commit -m "$commit_msg"
}
alias gcm="gcommit"
# Fetch, rebase and push updates to current branch
# Optionally specify target, defaults to 'master'
function gfetchrebase {
if ! [ -z "$1" ]; then
branch=$1
else
branch='master'
fi
git fetch upstream
git rebase upstream/$branch
git push
}
alias gfrb="gfetchrebase"
# Integrates with gitignore.io to auto-populate .gitignore file
function gignore() {
curl -fLw '\n' https://www.gitignore.io/api/"${(j:,:)@}"
}
_gitignoreio_get_command_list() {
curl -sfL https://www.gitignore.io/api/list | tr "," "\n"
}
_gitignoreio () {
compset -P '*,'
compadd -S '' `_gitignoreio_get_command_list`
}
# Downloads specific git ignore template to .gitignore
gignore-apply () {
if [ -n $search_term ]; then
gignore $1 >> .gitignore
else
echo "Expected a template to be specified. Run:"
echo " $ gignore list to view all options"
echo " $ gignore [template] to preview"
fi
}
# Helper function to return URL of current repo (based on origin)
get-repo-url() {
git_base_url='https://github.com'
# Get origin from git repo + remove .git
git_url=${$(git config --get remote.origin.url)%.git}
# Process URL, and append branch / working origin
if [[ $git_url =~ ^git@ ]]; then
branch=${1:-"$(git symbolic-ref --short HEAD)"}
branchExists="$(git ls-remote --heads $git_url $branch | wc -l)"
github="$(echo $git_url | sed 's/git@//')" # Remove git@ from the start
github="$(echo $github | sed 's/\:/\//')" # Replace : with /
if [[ $branchExists == " 1" ]]; then
git_url="http://$github/tree/$branch"
else
git_url="http://$github"
fi
elif [[ $git_url =~ ^https?:// ]]; then
branch=${1:-"$(git symbolic-ref --short HEAD)"}
branchExists="$(git ls-remote --heads $git_url $branch | wc -l)"
if [[ $branchExists == " 1" ]]; then
git_url="$git_url/tree/$branch"
else
git_url="$git_url"
fi
fi
# Return URL
echo $git_url
}
# Helper function that gets supported open method for system
launch-url() {
if hash open 2> /dev/null; then
open_command=open
elif hash xdg-open 2> /dev/null; then
open_command=xdg-open
elif hash lynx 2> /dev/null; then
open_command=lynx
else
echo -e "\033[0;33mUnable to launch browser, open manually instead"
echo -e "\033[1;96m🌐 URL: \033[0;96m\e[4m$1\e[0m"
return;
fi
echo $open_command
}
# Opens the current repo + branch in GitHub
open-github() {
git_base_url='https://github.com' # Modify this if using GH enterprise
if [[ ! -z $1 && ! -z $2 ]]; then
# User specified a repo
git_url=$git_base_url/$1/$2
elif git rev-parse --git-dir > /dev/null 2>&1; then
# Get URL from current repo's origin
git_url=$(get-repo-url)
else
# Not in repo, and nothing specified, open homepage
git_url=$git_base_url
fi
# Determine which open commands supported
open_command=$(launch-url $git_url)
# Print messages
echo -e "\033[1;96m🐙 Opening in browser: \033[0;96m\e[4m$git_url\e[0m"
# And launch!
$open_command $git_url
}
alias gho='open-github'
# Opens pull request tab for the current GH repo
open-github-pulls() {
# Get Repo URL
if git rev-parse --git-dir > /dev/null 2>&1; then
git_url=$(get-repo-url)
else
git_url='https://github.com'
fi
git_url="$git_url/pulls"
# Get open command
open_command=$(launch-url $git_url)
# Print message, and launch!
echo -e "\033[1;96m🐙 Opening in browser: \033[0;96m\e[4m$git_url\e[0m"
$open_command $git_url
}
alias ghp='open-github-pulls'
# Prompt for main SSH key passphrase, so u don't need to enter it again until session killed
alias add-key='eval "$(ssh-agent)" && ssh-add ~/.ssh/id_rsa'