├── bin ├── git-diff-from ├── pwd-tilde ├── git-commit-message-of-date ├── git-submodule-names ├── git-last-commit-id ├── git-rm-deleted ├── git-ls-conflicting-files ├── git-branch-current ├── git-edit-conflicting-files ├── git-flow-feature-branches ├── git-ensure-gitkeeps-in-all-directories ├── git-branch-current-is-feature ├── git-rebase-cleanly-or-abort ├── git-rebase-in-progress ├── git-file-is-tracked ├── git-revert-file-to-last-commit ├── git-is-git-flow-repo ├── git-append-branch-master-config ├── git-find ├── git-modified-files ├── git-count-untracked ├── git-edit-grep ├── git-delete-branch-on-remote ├── pwd-is-git-repo ├── git-metagrep ├── git-check-merge-conflicts ├── git-repositories-common-statuses ├── git-is-clean-work-tree ├── git-newly-defined-methods ├── git-merge-to ├── git-squash-latest-commits ├── git-rename-branch ├── git-rebase-from ├── git-status-display └── git-rebase-develop-into-feature-branches ├── misc └── g.png ├── .gitignore ├── ofe.json ├── LICENSE ├── README.md └── g.zsh /bin/git-diff-from: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | git diff HEAD...$1 4 | -------------------------------------------------------------------------------- /misc/g.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eriknomitch/g/HEAD/misc/g.png -------------------------------------------------------------------------------- /bin/pwd-tilde: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | echo $(pwd | sed -e "s,^$HOME,~,") 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore all swap files 2 | .*.swp 3 | 4 | .DS_Store 5 | .aider* 6 | -------------------------------------------------------------------------------- /bin/git-commit-message-of-date: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | git commit -a -m "`date`" 4 | -------------------------------------------------------------------------------- /bin/git-submodule-names: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | grep path .gitmodules | sed 's/.*= //' 3 | -------------------------------------------------------------------------------- /bin/git-last-commit-id: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | \git --no-pager log --format="%H" -n 1 4 | -------------------------------------------------------------------------------- /bin/git-rm-deleted: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | git ls-files --deleted | xargs git rm -f 4 | 5 | -------------------------------------------------------------------------------- /bin/git-ls-conflicting-files: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | \git diff --name-only --diff-filter=U 4 | -------------------------------------------------------------------------------- /bin/git-branch-current: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/' 4 | -------------------------------------------------------------------------------- /bin/git-edit-conflicting-files: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | #source $(dirname $0)/../g.zsh 4 | 5 | $EDITOR `git-ls-conflicting-files` 6 | -------------------------------------------------------------------------------- /bin/git-flow-feature-branches: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | git branch --no-color 2> /dev/null | sed "s/^. //g" | \grep -E "^feature\/" --color=never 4 | -------------------------------------------------------------------------------- /bin/git-ensure-gitkeeps-in-all-directories: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | for directory in `find ./ -type d`; do 4 | touch $directory/.gitkeep 5 | done 6 | -------------------------------------------------------------------------------- /bin/git-branch-current-is-feature: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if [[ `git-branch-current | grep -E "^feature/" | wc -l` -gt 0 ]] ; then 4 | return 0 5 | fi 6 | return 1 7 | -------------------------------------------------------------------------------- /bin/git-rebase-cleanly-or-abort: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | \git rebase $* || (\git rebase --abort; echo "fatal: The rebase had conflicts and has been aborted."; return 1) 4 | -------------------------------------------------------------------------------- /bin/git-rebase-in-progress: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | _git_dir=`git rev-parse --git-dir` 4 | _rebase_prefix="$_git_dir/rebase-merge" 5 | 6 | test -d "$_rebase_prefix" -o -d "$_git_dir"/rebase-apply 7 | -------------------------------------------------------------------------------- /bin/git-file-is-tracked: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # http://stackoverflow.com/questions/2405305/git-how-to-tell-if-a-file-is-git-tracked-by-shell-exit-code 4 | git ls-files $1 --error-unmatch &>/dev/null 5 | -------------------------------------------------------------------------------- /bin/git-revert-file-to-last-commit: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # FIX: Ensure git directory 4 | 5 | test -z $1 && echo "fatal: File path argument not passed." && return 1 6 | 7 | git checkout -- $1 8 | 9 | -------------------------------------------------------------------------------- /bin/git-is-git-flow-repo: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # FIX: Weak way to test it we're on a Git flow project 4 | if [[ `git branch | grep -E "^ feature/" | wc -l` -gt 0 ]] ; then 5 | exit 0 6 | fi 7 | exit 1 8 | -------------------------------------------------------------------------------- /bin/git-append-branch-master-config: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if [[ ! -d .git ]] ; then 4 | echo "fatal: Not a git repository" 5 | return 1 6 | fi 7 | 8 | echo "[branch \"master\"]\n\tremote = origin\n\tmerge = refs/heads/master" >> .git/config 9 | -------------------------------------------------------------------------------- /bin/git-find: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if [[ -z $1 ]] ; then 4 | echo "fatal: No find query passed." 5 | return 1 6 | fi 7 | 8 | # Add ./ to the file names to make it more like UNIX "find". 9 | git ls-files | grep -i $1 | sed "s/^/.\//" 10 | -------------------------------------------------------------------------------- /bin/git-modified-files: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | local modified_files 4 | 5 | modified_files=`\git diff --name-only` 6 | 7 | if [[ $1 == "--basename-only" ]] ; then 8 | echo $modified_files | xargs -n1 basename 9 | else 10 | echo $modified_files 11 | fi 12 | -------------------------------------------------------------------------------- /ofe.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": { 3 | "extensions": [".zsh", ".md"], 4 | "files": ["bin/*"], 5 | "first_file": "g.zsh" 6 | }, 7 | "docs": { 8 | "extensions": [".md"] 9 | }, 10 | "git": { 11 | "files": [".git/config", ".gitignore"] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /bin/git-count-untracked: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if ( `git rev-parse > /dev/null 2>&1` ) ; then 4 | if [[ "$HOST" == "linode" ]] ; then 5 | git ls-files -o --exclude-standard | wc -l 6 | else 7 | git ls-files --other --exclude-standard | wc -l | awk '{print $1}' 8 | fi 9 | fi 10 | -------------------------------------------------------------------------------- /bin/git-edit-grep: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | source $(dirname $0)/../g.zsh 4 | 5 | local files_found 6 | files_found=`git grep --name-only $*` 7 | 8 | echo $files_found 9 | echo 10 | 11 | if ( _prompt_success "Found these files for your query. Open them in your editor?" ) ; then 12 | echo $files_found | xargs bash -c ' /dev/null 2>&1` ) ; then 4 | 5 | # Switch for checking for root 6 | if [[ $1 == "--root" ]] ; then 7 | if [[ -e .git ]] ; then 8 | return 0 9 | fi 10 | return 1 11 | fi 12 | 13 | # We are on a git repo 14 | return 0 15 | fi 16 | 17 | # We aren't on a git repo 18 | return 1 19 | 20 | -------------------------------------------------------------------------------- /bin/git-metagrep: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | 4 | local grep_results 5 | 6 | 7 | grep_results=`\git grep "METAGREP: "` 8 | 9 | echo $grep_results | while read grep_result; do 10 | 11 | file_path=`echo $grep_result | awk '{print $1}' | sed "s/:$//"` 12 | metagrep_code=`echo $grep_result | sed "s/.*METAGREP: //"` 13 | 14 | echo $file_path 15 | rails runner "puts $metagrep_code" 16 | echo 17 | done 18 | 19 | -------------------------------------------------------------------------------- /bin/git-check-merge-conflicts: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | autoload colors 4 | colors 5 | 6 | if [[ -z $1 ]] ; then 7 | echo "usage: git-branch-conflicts-with " 8 | exit 1 9 | fi 10 | 11 | _branch=$1 12 | 13 | git merge --no-ff --no-commit $_branch 14 | echo 15 | 16 | if [[ `git-ls-conflicting-files | wc -l` -gt 0 ]] ; then 17 | print $fg_bold[yellow] "Conflicting files" $reset_color 18 | 19 | echo 20 | 21 | for file in `git-ls-conflicting-files`; do 22 | _conflicts=`\grep "<<<<<<< HEAD" $file | wc -l | sed "s/ //g"` 23 | print " $fg[red]" "("$_conflicts")"$fg_bold[white] $file$reset_color 24 | done 25 | 26 | echo 27 | 28 | fi 29 | 30 | git merge --abort 31 | -------------------------------------------------------------------------------- /bin/git-repositories-common-statuses: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | source /etc/zshrc-shared 4 | 5 | function git-repository-status 6 | { 7 | if [[ -n $1 ]] ; then 8 | repository_path=$1 9 | cd $repository_path > /dev/null 2>&1 10 | echo "------------------------------------" 11 | pwd-tilde 12 | echo "------------------------------------" 13 | g 14 | fi 15 | } 16 | 17 | # ------------------------------------------------ 18 | # MAIN ------------------------------------------- 19 | # ------------------------------------------------ 20 | git-repository-status ~/.bin 21 | git-repository-status ~/.configs 22 | git-repository-status ~/.meta 23 | git-repository-status ~/.meta-materials 24 | 25 | -------------------------------------------------------------------------------- /bin/git-is-clean-work-tree: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | # Ensure we're on a Git repo 4 | pwd-is-git-repo || return 1 5 | 6 | # Update the index 7 | # FIX: This seems to be doing funny things with the status when run. 8 | git update-index -q --ignore-submodules --refresh 9 | 10 | # Are there any file changes? 11 | if ! git diff-files --quiet --ignore-submodules ; then 12 | return 1 13 | fi 14 | 15 | # Are there any text changes? 16 | if ! git diff-index --cached --quiet --ignore-submodules HEAD -- ; then 17 | return 1 18 | fi 19 | 20 | # Are there untracked files? 21 | # 22 | # FIX: I think you can remove this... I think it should get caught by the 23 | # diff-files. 24 | if [[ `git-count-untracked` -gt 0 ]] ; then 25 | return 1 26 | fi 27 | 28 | return 0 29 | -------------------------------------------------------------------------------- /bin/git-newly-defined-methods: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | function _newly_defined_ruby_methods() 4 | { 5 | local new_ruby_methods 6 | 7 | # FIX: Needs to see if this method has just moved (would still have "+ "). Check vs "- " 8 | 9 | # Find + def, strip def, strip arguments, replace newline with ", " 10 | new_ruby_methods=`git diff | \grep --color=never -E "^\+ *def " | sed "s/^+ *def //" | sed "s/(.*//" | tr "\n" "," ` 11 | 12 | # Strip trailing ", " delimiter 13 | new_ruby_methods=`echo -n $new_ruby_methods | sed "s/,$//"` 14 | 15 | # Replace delimters with ", " because tr can't do it (or I don't know how) 16 | new_ruby_methods=`echo $new_ruby_methods | sed "s/,/, /g"` 17 | 18 | echo "+rb: "$new_ruby_methods 19 | } 20 | 21 | _newly_defined_ruby_methods 22 | 23 | -------------------------------------------------------------------------------- /bin/git-merge-to: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | source $(dirname $0)/../g.zsh 4 | 5 | _branch_destination=$1 6 | _branch_current=`git-branch-current` 7 | 8 | if [[ -z $_branch_destination ]] ; then 9 | echo "fatal: No destination branch supplied." 10 | return 1 11 | fi 12 | 13 | _prompt_warning "Are you sure you want to merge '$_branch_current' into '$_branch_destination'?" || exit 1 14 | 15 | echo "Checking out '$_branch_destination'" 16 | git checkout $_branch_destination || exit 1 17 | 18 | echo "Merging '$_branch_current'" 19 | git merge $_branch_current || exit 1 20 | 21 | echo 22 | echo "Merge successful." 23 | echo 24 | 25 | if _prompt_success "Push '$_branch_destination' to default remote?"; then 26 | git push 27 | fi 28 | 29 | echo "Checking out '$_branch_current'" 30 | git checkout $_branch_current || exit 1 31 | 32 | echo 33 | echo "Success. Merged '$_branch_current' into '$_branch_destination' and returned to '$_branch_current'" 34 | 35 | -------------------------------------------------------------------------------- /bin/git-squash-latest-commits: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | source $(dirname $0)/../g.zsh 4 | 5 | if [[ -z $1 || $1 == "--help" || $1 == "-h" ]] ; then 6 | echo "usage: git-squash-latest-commits " 7 | exit 1 8 | fi 9 | 10 | if ! git-is-clean-work-tree; then 11 | echo "fatal: Your work tree is not clean. Stash or commit first." 12 | exit 1 13 | fi 14 | 15 | # ------------------------------------------------ 16 | # MAIN ------------------------------------------- 17 | # ------------------------------------------------ 18 | _latest_n=$1 19 | 20 | git log -n $_latest_n --oneline 21 | echo 22 | 23 | if _prompt_warning "Squash these commits? You'll be able to edit the new commit message will start as these combined."; then 24 | # SEE: https://stackoverflow.com/questions/5189560/squash-my-last-x-commits-together-using-git/5201642#5201642 25 | git reset --soft HEAD~$_latest_n && \ 26 | git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{$_latest_n})" && \ 27 | echo "Squashed/committed. You may need to 'git push --force' since this changed history." 28 | fi 29 | 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2012 Erik Nomitch, http://eriknomitch.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /bin/git-rename-branch: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | source $(dirname $0)/../g.zsh 4 | 5 | function _usage() { 6 | echo "usage: [BRANCH-TO-RENAME] " 7 | } 8 | 9 | function _usage_and_exit() { 10 | _usage 11 | exit 1 12 | } 13 | 14 | # ------------------------------------------------ 15 | # ------------------------------------------------ 16 | # ------------------------------------------------ 17 | if [[ $# = 1 ]]; then 18 | _current_branch_name=`git-branch-current` 19 | _new_branch_name=$1 20 | elif [[ $# = 2 ]] ; then 21 | _current_branch_name=$1 22 | _new_branch_name=$2 23 | else 24 | _usage_and_exit 25 | fi 26 | 27 | if [[ $_current_branch_name = "master" ]]; then 28 | echo "fatal: You cannot rename the master branch." 29 | exit 1 30 | fi 31 | 32 | echo "This will rename branch $_current_branch_name to $_new_branch_name locally." 33 | echo 34 | 35 | if ! _prompt_warning "Continue?"; then 36 | exit 37 | fi 38 | 39 | git branch -m $_current_branch_name $_new_branch_name 40 | 41 | echo "Delete the old branch $_current_branch_name on origin and push the new branch to origin?" 42 | if ! _prompt_warning "Continue?"; then 43 | exit 44 | fi 45 | 46 | git push origin :$_current_branch_name 47 | git push --set-upstream $_new_branch_name origin 48 | -------------------------------------------------------------------------------- /bin/git-rebase-from: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | source $(dirname $0)/../g.zsh 4 | 5 | local _original_branch 6 | local _target_branch 7 | local _yes 8 | 9 | _original_branch=`git-branch-current` 10 | _target_branch=$1 11 | _yes=false 12 | 13 | if [[ $2 == "--yes" ]] ; then 14 | _yes=true 15 | fi 16 | 17 | if ( ! git-is-clean-work-tree ) ; then 18 | echo "fatal: Your Git work tree is not clean. Commit or stash your changes first." 19 | exit 1 20 | fi 21 | 22 | if [[ -z $_target_branch ]] ; then 23 | echo "fatal: Did not pass target branch." 24 | exit 1 25 | fi 26 | 27 | if [[ $_target_branch == $_original_branch ]] ; then 28 | echo "fatal: You are already on branch '$_target_branch'." 29 | exit 1 30 | fi 31 | 32 | if ( $_yes || _prompt_warning "Are you sure you want to rebase '$_original_branch' from '$_target_branch'?" ) ; then 33 | git checkout "$_target_branch" 34 | git rebase "$_original_branch" 35 | 36 | # Rebase succceeded 37 | if [[ $? == 0 ]] ; then 38 | 39 | echo 40 | echo "Rebase successful." 41 | echo 42 | 43 | if ( $_yes || _prompt_success "Push '$_target_branch' to default remote?" ) ; then 44 | git push 45 | fi 46 | 47 | if ( $_yes || _prompt_success "Return to branch '$_original_branch'?" ) ; then 48 | git checkout "$_original_branch" 49 | fi 50 | 51 | # Rebase failed 52 | else 53 | echo "fatal: Rebase failed. Leaving you in '$_target_branch'." 54 | exit 1 55 | fi 56 | fi 57 | 58 | -------------------------------------------------------------------------------- /bin/git-status-display: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if ( ! `pwd-is-git-repo` ) ; then 4 | exit 1 5 | fi 6 | 7 | # FIX: this says that the dir is clean when we deleted some files and when we git-mv files. probably more 8 | local git_count_untracked 9 | local git_count_branches 10 | local git_branch_current 11 | 12 | git_count_untracked=`git-count-untracked` 13 | git_count_branches=`git branch | wc -l | awk '{print $1}'` 14 | git_branch_current=`git-branch-current` 15 | 16 | echo -en "\033[30;1mgit:\033[0m " 17 | 18 | # Show branches 19 | echo -e "branch: \033[37;1m"$git_branch_current"\033[0m("$git_count_branches")" 20 | 21 | # Show status 22 | echo -en " \033[37;mstatus:\033[0m " 23 | 24 | # Check status 25 | if ( `git-is-clean-work-tree` ) ; then 26 | echo -e "\033[32;1mclean\033[0m " 27 | else 28 | echo -e "\033[31;1munclean\033[0m " 29 | fi 30 | 31 | # Show diff 32 | echo -e " \033[37;mdiff:\033[0m \033[37;1m"`git diff --shortstat`"\033[0m" 33 | git diff --numstat | sed "s/^/ /" 34 | 35 | # Show untracked files 36 | echo -e " \033[37;muntracked:\033[0m \033[37;1m"$git_count_untracked"\033[0m" 37 | 38 | git ls-files --other --exclude-standard | sed "s/^/ /" 39 | 40 | # Git flow display if Git flow project 41 | # FIX: Weak way to test it we're on a Git flow project 42 | if ( `git-is-git-flow-repo` ) ; then 43 | 44 | # FIX: Zero features... 45 | git_count_features=`git-flow-feature-branches | wc -l | sed "s/ *//"` 46 | 47 | echo -e " \033[37;mfeatures: \033[0m \033[37;1m"$git_count_features"\033[0m" 48 | #git flow feature | sed "s/^/ /" 49 | fi 50 | -------------------------------------------------------------------------------- /bin/git-rebase-develop-into-feature-branches: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | source $(dirname $0)/../g.zsh 4 | 5 | if ( ! `git-is-clean-work-tree` ) ; then 6 | echo "fatal: Your Git work tree is not clean. Commit or stash your changes first." 7 | exit 1 8 | fi 9 | 10 | _original_branch=`git-branch-current` 11 | 12 | for _feature_branch in `git-flow-feature-branches`; do 13 | if ( _prompt_success "Attempt to rebase 'develop' into '$_feature_branch'?" ) ; then 14 | 15 | git checkout "$_feature_branch" 16 | git rebase develop 17 | 18 | # Rebase failed 19 | if [[ $? != 0 ]] ; then 20 | echo "warning: Rebase of 'develop' into '$_feature_branch' was not successful." 21 | echo 22 | 23 | echo "Your options are:" 24 | echo " a) Abort rebase of this branch and move on to next feature branch." 25 | echo " x) Exit and attempt to fix rebase of this branch." 26 | 27 | echo -n "> " 28 | read decision 29 | 30 | case $decision in 31 | a) 32 | git rebase --abort 33 | ;; 34 | x) 35 | echo "Exiting in branch '$_feature_branch'." 36 | exit 1 37 | ;; 38 | esac 39 | 40 | # Rebase was successful 41 | else 42 | echo 43 | echo "Rebase successful." 44 | echo 45 | if ( _prompt_success "-> Do you want to push this branch '$_feature_branch' to your default remote?") ; then 46 | 47 | git push 48 | 49 | if [[ $? != 0 ]] ; then 50 | 51 | echo 52 | echo "Push failed. You probably need to force push." 53 | echo 54 | 55 | if ( _prompt_warning " -> Do you want to force push this branch '$_feature_branch' to your default remote? WARNING: This a potentially destructive action.") ; then 56 | git push --force 57 | fi 58 | fi 59 | fi 60 | fi 61 | 62 | fi 63 | done 64 | 65 | git checkout "$_original_branch" 66 | echo 67 | echo "Done. You are now on your original branch '$_original_branch'" 68 | 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # g 2 | A collection of Zsh functions to augment Git. 3 | 4 | ![g](https://raw.github.com/eriknomitch/g/master/misc/g.png) 5 | 6 | ## Requirements 7 | * Zsh 8 | * Git 9 | 10 | ## Installation 11 | 12 | Clone the repository to `~/.g` and add `source $HOME/.g/g.zsh` to your `~/.zshrc`. 13 | 14 | Here's a one-liner: 15 | 16 | ```Bash 17 | $ git clone https://github.com/eriknomitch/g.git ~/.g && echo "source \$HOME/.g/g.zsh" >> ~/.zshrc 18 | ``` 19 | 20 | Then, quit and restart your terminal instances. 21 | 22 | **Note:** If you use `oh-my-zsh` with the `git` plug-in, you'll have to disable it. 23 | 24 | ## Commands 25 | 26 | **g** 27 | 28 | Without arguments, *g* will display a custom, colored, and formatted git status including: 29 | 30 | * Repository status (clean or unclean) 31 | * Current branch and number of branches 32 | * List of untracked files 33 | * Short diff 34 | 35 | Any arguments to *g* will first try to match a shortcut. If a *g* shortcut is not matched, arguments to *g* will fall back to git allowing usage of *g* as a normal alias to `git`. 36 | 37 | ### Automatically Run `g` on Directory Change 38 | 39 | I highly recommend this. 40 | 41 | Add to the end of your `~/.zshrc` file: 42 | 43 | ```Shell 44 | chpwd() { _g_chpwd } 45 | ``` 46 | 47 | One-liner: 48 | 49 | ```Shell 50 | echo "chpwd() { _g_chpwd }" >> ~/.zshrc 51 | ``` 52 | 53 | ### Quick Commands 54 | 55 | **g cm \** 56 | 57 | *Commit all with message* 58 | 59 | **g cmp \** 60 | 61 | *Commit all with message and push* 62 | 63 | ### Prompts 64 | 65 | **g au** 66 | 67 | Prompts to add all untracked files in the current repository 68 | 69 | **g ru** 70 | 71 | Prompts to remove all untracked files in the current directory 72 | 73 | ### Aliases 74 | 75 | **g l** 76 | 77 | `git log` 78 | 79 | **g b** 80 | 81 | `git branch` 82 | 83 | **g d** 84 | 85 | `git diff` 86 | 87 | **g s** 88 | 89 | `git status` 90 | 91 | **g ls** 92 | 93 | `git ls-files` 94 | 95 | **g lsd** 96 | 97 | `git ls-files --deleted` 98 | 99 | **g lso** 100 | 101 | *List untracked files excluding ignored files* 102 | 103 | `git ls-files --other --exclude-standard` 104 | 105 | **g ps** 106 | 107 | `git push` 108 | 109 | **g psa** 110 | 111 | `git push all` 112 | 113 | **g pl** 114 | 115 | `git pull` 116 | 117 | Credits 118 | ------- 119 | Erik Nomitch: erik@nomitch.com 120 | -------------------------------------------------------------------------------- /g.zsh: -------------------------------------------------------------------------------- 1 | # ================================================ 2 | # G ============================================== 3 | # ================================================ 4 | 5 | # ------------------------------------------------ 6 | # COLORS ----------------------------------------- 7 | # ------------------------------------------------ 8 | # 30 - black 9 | # 31 - red 10 | # 32 - green 11 | # 33 - yellow 12 | # 34 - blue 13 | # 35 - magenta 14 | # 36 - cyan 15 | # 37 - white 16 | # 17 | # 0 - normal 18 | # 1 - bold 19 | # 2 - normal again 20 | # 3 - background color 21 | # 4 - underline the text 22 | # 5 - blinking 23 | 24 | 25 | # http://stackoverflow.com/questions/16843382/colored-shell-script-output-library 26 | RCol='\e[0m' # Text Reset 27 | 28 | # Regular Bold Underline High Intensity BoldHigh Intens Background High Intensity Backgrounds 29 | Bla='\e[0;30m'; BBla='\e[1;30m'; UBla='\e[4;30m'; IBla='\e[0;90m'; BIBla='\e[1;90m'; On_Bla='\e[40m'; On_IBla='\e[0;100m'; 30 | Red='\e[0;31m'; BRed='\e[1;31m'; URed='\e[4;31m'; IRed='\e[0;91m'; BIRed='\e[1;91m'; On_Red='\e[41m'; On_IRed='\e[0;101m'; 31 | Gre='\e[0;32m'; BGre='\e[1;32m'; UGre='\e[4;32m'; IGre='\e[0;92m'; BIGre='\e[1;92m'; On_Gre='\e[42m'; On_IGre='\e[0;102m'; 32 | Yel='\e[0;33m'; BYel='\e[1;33m'; UYel='\e[4;33m'; IYel='\e[0;93m'; BIYel='\e[1;93m'; On_Yel='\e[43m'; On_IYel='\e[0;103m'; 33 | Blu='\e[0;34m'; BBlu='\e[1;34m'; UBlu='\e[4;34m'; IBlu='\e[0;94m'; BIBlu='\e[1;94m'; On_Blu='\e[44m'; On_IBlu='\e[0;104m'; 34 | Pur='\e[0;35m'; BPur='\e[1;35m'; UPur='\e[4;35m'; IPur='\e[0;95m'; BIPur='\e[1;95m'; On_Pur='\e[45m'; On_IPur='\e[0;105m'; 35 | Cya='\e[0;36m'; BCya='\e[1;36m'; UCya='\e[4;36m'; ICya='\e[0;96m'; BICya='\e[1;96m'; On_Cya='\e[46m'; On_ICya='\e[0;106m'; 36 | Whi='\e[0;37m'; BWhi='\e[1;37m'; UWhi='\e[4;37m'; IWhi='\e[0;97m'; BIWhi='\e[1;97m'; On_Whi='\e[47m'; On_IWhi='\e[0;107m'; 37 | 38 | # TODO: g cmp should check to see if the last commit had the same message as the 39 | # one you're trying to create and it should prompt. 40 | 41 | # ------------------------------------------------ 42 | # CONSTANTS -------------------------------------- 43 | # ------------------------------------------------ 44 | _VERBOSE=false 45 | 46 | # ------------------------------------------------ 47 | # GLOBALS ---------------------------------------- 48 | # ------------------------------------------------ 49 | _matches=() 50 | _bodies=() 51 | _commands_length=0 52 | 53 | # Find the Git completion file path 54 | _git_completion_path=`echo -n ${^fpath}/_git(N)` 55 | 56 | # ------------------------------------------------ 57 | # CONFIG->ZSH ------------------------------------ 58 | # ------------------------------------------------ 59 | 60 | # We source the existing Git rules here so we have access to various 61 | # autocompletion rules. 62 | if [[ -f $_git_completion_path ]] ; then 63 | source $_git_completion_path 64 | fi 65 | 66 | # Append g auxiliary scripts to $PATH 67 | export PATH=$PATH:$(dirname $0)/bin 68 | 69 | _g_eza_tree () { 70 | local options=(--icons --classify --oneline --long \ 71 | --no-permissions --no-user \ 72 | --time-style relative --git \ 73 | --level 1 --tree) 74 | 75 | [[ $1 == 't' ]] && options+=(--sort time --reverse) 76 | eza "${options[@]}" 77 | } 78 | 79 | _g_ls() 80 | { 81 | if [[ `uname` == "Darwin" && -n `which eza` ]] ; then 82 | _g_eza_tree t 83 | else 84 | ls -lh --color 85 | fi 86 | } 87 | 88 | # Change working directory Zsh rule 89 | _g_chpwd() 90 | { 91 | # Check for shell level (SHLVL) beacuse we don't want this happening in scripts. 92 | # 93 | # Check for $0 to be 'zsh' because we don't want this happening in functions. 94 | # FIX: Doesn't work. ^^^ 95 | #if [[ $SHLVL -lt 1 || $SKIP_CHPWD == true ]] ; then 96 | if [ -n "${SKIP_CHPWD+x}" ]; then 97 | if ( $SKIP_CHPWD ) ; then 98 | return 0 99 | fi 100 | fi 101 | 102 | # FIX: IMPORTANT: This is specific to you... 103 | if [[ $SHLVL == 1 || -n $TMUX ]] ; then 104 | _g_ls 105 | fi 106 | 107 | if ( `pwd-is-git-repo --root` ) ; then 108 | git-status-display 109 | fi 110 | 111 | if ( `pwd-is-git-repo --root` ) ; then 112 | echo -e "\033[30;1mpwd:\033[0m \033[33;2m`pwd-tilde`\033[0m" 113 | fi 114 | 115 | if [[ -f .directory-metadata ]] ; then 116 | source .directory-metadata 117 | 118 | _metadata_title=`echo -n "${BIRed}$_directory_title${RCol}"` 119 | _metadata_title_length=${#_directory_title} 120 | _metadata_bar=`head -c $_metadata_title_length < /dev/zero | tr '\0' '-'`"------" 121 | 122 | if [[ -z $_directory_title_color ]] ; then 123 | _directory_title_color="red" 124 | fi 125 | 126 | echo 127 | #echo "${On_IWhi}$_metadata_bar${RCol}" 128 | print -P '%B%F{$_directory_title_color}$_directory_title%f%b' 129 | #echo "${On_IWhi}$_metadata_bar${RCol}" 130 | echo 131 | fi 132 | } 133 | 134 | # ------------------------------------------------ 135 | # UTILITY->SHELL --------------------------------- 136 | # ------------------------------------------------ 137 | function _echo_verbose() 138 | { 139 | if ( $_VERBOSE ) ; then 140 | echo $* 141 | fi 142 | } 143 | 144 | function _read_prompt_response() 145 | { 146 | read _response 147 | 148 | if [[ $_response == "y" ]] ; then 149 | return 0 150 | fi 151 | return 1 152 | } 153 | 154 | function _prompt_success() 155 | { 156 | echo -en "\033[32;1m$1 (y/n) \033[0m" 157 | _read_prompt_response 158 | } 159 | 160 | function _prompt_warning() 161 | { 162 | echo -en "\033[33;1m$1 (y/n) \033[0m" 163 | _read_prompt_response 164 | } 165 | 166 | function _prompt_danger() 167 | { 168 | echo -en "\033[31;1m$1 (y/n) \033[0m" 169 | _read_prompt_response 170 | } 171 | 172 | # ------------------------------------------------ 173 | # UTILITY->GIT ----------------------------------- 174 | # ------------------------------------------------ 175 | function _git_prompt_if_untracked_files() 176 | { 177 | # Any untracked files? 178 | if [[ -n `git ls-files --other --exclude-standard` ]] ; then 179 | 180 | # Show them 181 | echo $g_lso 182 | 183 | _prompt_warning "Untracked files exist. Commit anyways?" 184 | 185 | return $? 186 | fi 187 | 188 | # There were no untracked files 189 | return 0 190 | } 191 | 192 | function _prompt_and_force_push() 193 | { 194 | if ( _prompt_danger "Force push this branch '`git-branch-current`' to your default remote? WARNING: This is potentially destructive." ) ; then 195 | git push --force 196 | fi 197 | } 198 | 199 | # ------------------------------------------------ 200 | # COMMANDS --------------------------------------- 201 | # ------------------------------------------------ 202 | function _define_command() 203 | { 204 | # Push the match and body for that match 205 | _matches+=($1) 206 | shift 207 | _bodies+=($*) 208 | 209 | let "_commands_length += 1" 210 | } 211 | 212 | function _find_command() 213 | { 214 | _find_match=$1 215 | 216 | # FIX: This is breaking unless it's <= instead of <... Why? 217 | for (( index = 0 ; index <= $_commands_length ; index++)) ; do 218 | if [[ $_find_match == $_matches[$index] ]] ; then 219 | echo $_bodies[$index] 220 | return 0 221 | fi 222 | done 223 | 224 | return 1 225 | } 226 | 227 | # ------------------------------------------------ 228 | # DEFINE->HELPERS -------------------------------- 229 | # ------------------------------------------------ 230 | 231 | # FIX: Use git-is-clean-work-tree 232 | function _git_is_clean_work_tree() { 233 | git rev-parse --verify HEAD >/dev/null || return 1 234 | git update-index -q --ignore-submodules --refresh 235 | 236 | if ! git diff-files --quiet --ignore-submodules ; then 237 | return 1 238 | fi 239 | 240 | if ! git diff-index --cached --quiet --ignore-submodules HEAD -- ; then 241 | return 1 242 | fi 243 | 244 | # Are there untracked files? 245 | if [[ `git-count-untracked` -gt 0 ]] ; then 246 | return 1 247 | fi 248 | 249 | return 0 250 | } 251 | 252 | #function _git_status_display() 253 | #{ 254 | ## FIX: this says that the dir is clean when we deleted some files and when we git-mv files. probably more 255 | #git_count_untracked=`git-count-untracked` 256 | #git_count_branches=`git branch | wc -l | awk '{print $1}'` 257 | #git_branch_current=`git-branch-current` 258 | 259 | #echo -en "\033[30;1mgit:\033[0m " 260 | 261 | ## Show branches 262 | #echo -e "branch: \033[37;1m"$git_branch_current"\033[0m("$git_count_branches")" 263 | 264 | ## Show status 265 | #echo -en " \033[37;mstatus:\033[0m " 266 | 267 | ## Check status 268 | #_git_is_clean_work_tree 269 | 270 | #if [[ $? == 0 ]] ; then 271 | #echo -e "\033[32;1mclean\033[0m " 272 | #else 273 | #echo -e "\033[31;1munclean\033[0m " 274 | #fi 275 | 276 | ## Show diff 277 | #echo -e " \033[37;mdiff:\033[0m \033[37;1m"`git diff --shortstat`"\033[0m" 278 | #git diff --numstat | sed "s/^/ /" 279 | 280 | ## Show untracked 281 | #echo -e " \033[37;muntracked:\033[0m \033[37;1m"$git_count_untracked"\033[0m" 282 | 283 | #g lso | sed "s/^/ /" 284 | #} 285 | 286 | function _git_all_tracked_or_prompt() 287 | { 288 | local g_lso 289 | 290 | g_lso=`git ls-files --other --exclude-standard` 291 | 292 | if [[ -n $g_lso ]] ; then 293 | echo $g_lso 294 | 295 | if ( _prompt_success "Add these files to be tracked?" ) ; then 296 | git add . 297 | fi 298 | fi 299 | } 300 | 301 | function _git_remove_untracked_prompt() 302 | { 303 | local g_lso 304 | 305 | g_lso=`git ls-files --other --exclude-standard` 306 | 307 | if [[ -n $g_lso ]] ; then 308 | echo $g_lso 309 | echo -en "\033[31;1mPermanently remove these files (y/n)?\033[0m " 310 | read add_files 311 | 312 | if [[ $add_files == "y" ]] ; then 313 | # FIX: Does this handle directories? I think so... 314 | echo $g_lso | xargs rm 315 | fi 316 | fi 317 | } 318 | 319 | function _git_fallback() 320 | { 321 | _echo_verbose "g: Falling back to git with 'git $*'" 322 | eval "git $*" 323 | } 324 | 325 | # ------------------------------------------------ 326 | # DEFINE->COMMANDS->ALIASES ---------------------- 327 | # ------------------------------------------------ 328 | # Define the commands and also define special 329 | # special _git-* functions for aliases. See /usr/share/zsh/functions/Completion/Unix/_git for documentation on this. 330 | _define_command g "git grep" 331 | function _git-g () { 332 | _git-grep 333 | } 334 | 335 | _define_command l "git log" 336 | function _git-l () { 337 | _git-log 338 | } 339 | 340 | _define_command ls "git ls-files" 341 | function _git-ls () { 342 | _git-ls-files 343 | } 344 | 345 | _define_command b "git branch" 346 | function _git-b () { 347 | _git-branch 348 | } 349 | 350 | _define_command d "git diff" 351 | function _git-d () { 352 | _git-diff 353 | } 354 | 355 | _define_command s "git status" 356 | function _git-s () { 357 | _git-status 358 | } 359 | 360 | _define_command ps "git push" 361 | function _git-ps () { 362 | _git-push 363 | } 364 | 365 | _define_command pl "git pull" 366 | function _git-pl () { 367 | _git-pull 368 | } 369 | 370 | _define_command co "git checkout" 371 | function _git-co () { 372 | _git-checkout 373 | } 374 | 375 | _define_command t "git tag" 376 | function _git-t () { 377 | _git-tag 378 | } 379 | 380 | _define_command ss "git status --short" 381 | _define_command psa "git push --all" 382 | _define_command lso "git ls-files --other --exclude-standard" 383 | _define_command lsd "git ls-files --deleted" 384 | _define_command a "git auto" 385 | _define_command ff "git flow feature" 386 | _define_command u "git up" 387 | _define_command rnm "git branch --remote --no-merged" 388 | _define_command rdf "git-rebase-develop-into-feature-branches" 389 | _define_command rfm "git-rebase-from master" 390 | _define_command rfmy "git-rebase-from master --yes" 391 | _define_command asd "git-auto-smart-diff" 392 | _define_command eg "git-edit-grep" 393 | 394 | # IDEA: Add g cfp which makes a message with the files changed appended to the 395 | # message. 396 | 397 | # ------------------------------------------------ 398 | # DEFINE->COMMANDS->SPECIAL ---------------------- 399 | # ------------------------------------------------ 400 | 401 | # Untracked file handling 402 | _define_command au "_git_all_tracked_or_prompt" 403 | _define_command ru "_git_remove_untracked_prompt" 404 | 405 | # Commit with message 406 | _define_command cm "_git_commit_with_message" 407 | _define_command cmp "_git_commit_with_message -p" 408 | 409 | # Commit with short stat diff 410 | _define_command cs "_git_commit_with_message -s" 411 | _define_command csp "_git_commit_with_message -p -s" 412 | 413 | # Commit with auto smart diff 414 | _define_command ca "_git_commit_with_message -a" 415 | _define_command cap "_git_commit_with_message -p -a" 416 | 417 | # Commit with line diff 418 | _define_command cl "_git_commit_line_diff" 419 | _define_command clp "_git_commit_line_diff -p" 420 | 421 | # Shell commands 422 | # FIX: Make this _git_execute and "x" 423 | _define_command c "_git_command" 424 | 425 | # Chained grep 426 | _define_command cg "_git_chained_grep" 427 | 428 | # Ammend message 429 | _define_command am "_git_ammend_message" 430 | 431 | # Rebase Continue (adds and continues) 432 | _define_command rc "_git_rebase_continue" 433 | 434 | # cg: Chained Grep 435 | # ------------------------------------------------ 436 | # Run a command and commit with the message of the command. 437 | function _git_chained_grep() 438 | { 439 | query_string="" 440 | multi_grep="(`echo $* | tr " " "|"`)" 441 | 442 | for query in $* 443 | do 444 | query_string+=$query" | grep " 445 | done 446 | 447 | query_string+="--color -E '$multi_grep'" 448 | 449 | eval "git grep $query_string" 450 | } 451 | 452 | # c: Git Command 453 | # ------------------------------------------------ 454 | # Run a command and commit with the message of the command. 455 | function _git_command() 456 | { 457 | initial_arguments=$* 458 | 459 | # Execute all the arguments 460 | $* 461 | 462 | # Command was successful; Continue 463 | if [[ $? == 0 ]] ; then 464 | 465 | _git_all_tracked_or_prompt 466 | 467 | git commit --all -m $initial_arguments 468 | 469 | # Command failed 470 | else 471 | echo "fatal: Command failed. Not commiting." 472 | return 1 473 | fi 474 | } 475 | 476 | # c: Git Commit with Message 477 | # ------------------------------------------------ 478 | # Commit all with a message and possibly push. 479 | function _git_commit_with_message() 480 | { 481 | # Parse arguments 482 | # FIX: Really? What's a better way to get opts as booleans? 483 | zparseopts -- p=push s=status_as_message a=auto_as_message 484 | 485 | _push=false 486 | _status_as_message=false 487 | _auto_as_message=false 488 | 489 | if [[ $push == "-p" ]] ; then 490 | _push=true 491 | shift 492 | fi 493 | 494 | if [[ $status_as_message == "-s" ]] ; then 495 | _status_as_message=true 496 | shift 497 | fi 498 | 499 | if [[ $auto_as_message == "-a" ]] ; then 500 | _auto_as_message=true 501 | shift 502 | fi 503 | 504 | # Set commit message to something special? 505 | local _commit_message 506 | 507 | # Short stat: 508 | if ( $_status_as_message ) ; then 509 | 510 | # Replace line breaks with ; and chomp the trailing ; 511 | _commit_message=`echo \`git status -s | tr "\n" ";"\` | sed "s/;$//g"` 512 | 513 | # Auto smart diff: 514 | elif ( $_auto_as_message ) ; then 515 | 516 | local _prefix 517 | local _auto_smart_diff 518 | 519 | _prefix="" 520 | _auto_smart_diff=`git-auto-smart-diff --short` 521 | 522 | if [[ -z $_auto_smart_diff ]] ; then 523 | echo "fatal: Cannot commit an auto smart diff if the auto smart diff is empty." 524 | return 1 525 | fi 526 | 527 | # If we have more arguments prefix them to the commit message. 528 | if [[ -n $* ]] ; then 529 | _prefix="$*: " 530 | fi 531 | 532 | _commit_message="$_prefix$_auto_smart_diff" 533 | 534 | # Otherwise, just the argument 535 | else 536 | _commit_message=$1 537 | 538 | shift 539 | 540 | # If we still have arguments, we want to only commit 541 | # these files. 542 | _select_files="" 543 | 544 | if [[ $# -gt 0 ]] ; then 545 | _select_files="$*" 546 | fi 547 | 548 | fi 549 | 550 | # Check for commit message 551 | if [[ -z $_commit_message ]] ; then 552 | echo "fatal: Cannot commit with an empty message." 553 | return 1 554 | fi 555 | 556 | # Confirm short stat commit message 557 | if ( $_status_as_message ) ; then 558 | echo $_commit_message 559 | if ( ! _prompt_success "Commit with this short stat as message?" ) ; then 560 | return 1 561 | fi 562 | fi 563 | 564 | # Any untracked files? 565 | _git_prompt_if_untracked_files 566 | 567 | # Perform the commit 568 | if [[ $? == 0 ]] ; then 569 | 570 | # We're committing all files 571 | if [[ -z $_select_files ]] ; then 572 | git commit --all --message "$_commit_message" 573 | 574 | # We're only commiting certain files 575 | else 576 | git commit --message "$_commit_message" $_select_files 577 | fi 578 | 579 | # Perform the push? 580 | if ( $_push ) ; then 581 | git push 582 | fi 583 | 584 | # Status display 585 | g 586 | fi 587 | } 588 | 589 | # cl: Git commit line diff 590 | # ------------------------------------------------ 591 | # Commit all with a message of only the lines changed. 592 | function _git_commit_line_diff() 593 | { 594 | zparseopts -- p=push s=status_as_message 595 | 596 | _push=false 597 | if [[ $push == "-p" ]] ; then 598 | _push=true 599 | fi 600 | 601 | # Check if we have anything to commit. 602 | if ( _git_is_clean_work_tree) ; then 603 | echo "Nothing to commit." 604 | return 1 605 | fi 606 | 607 | # Diff the repository to create the message: 608 | # 609 | # First, match the lines that begin with + or -... Then, omit the filename 610 | # descriptor lines (i.e., +++ or ---). 611 | local _commit_message 612 | _commit_message=`git diff | grep -E "^\+|^\-" | grep -vE "^\+{3}|^\-{3}"` 613 | 614 | if [[ $_commit_message == "" ]] ; then 615 | echo "fatal: Cannot commit with an empty message (i.e., there is no line diff)." 616 | return 1 617 | fi 618 | 619 | # FIX: This will echo in color if shell code contains color characters. 620 | echo $_commit_message 621 | 622 | if ( _prompt_success "Commit with this line diff as message?" ) ; then 623 | git commit --all --message "$_commit_message" 624 | 625 | if ( $_push ) ; then 626 | git push 627 | fi 628 | fi 629 | } 630 | 631 | # am: Ammend message 632 | # ------------------------------------------------ 633 | # Ammend the last commit message and prompt to force push. 634 | function _git_ammend_message() 635 | { 636 | local _commit_message 637 | 638 | if [[ -n $1 ]] ; then 639 | _commit_message=$1 640 | else 641 | echo "Your latest commit is:" 642 | echo 643 | 644 | git log -n 1 645 | 646 | echo 647 | echo -n "Enter your ammended commit message: " 648 | read _commit_message 649 | fi 650 | 651 | if ( git commit --all --amend --message "$_commit_message" ) ; then 652 | 653 | echo 654 | echo "Ammended." 655 | echo 656 | 657 | _prompt_and_force_push 658 | 659 | fi 660 | } 661 | 662 | # rc: Rebase continue 663 | # ------------------------------------------------ 664 | function _git_rebase_continue() 665 | { 666 | if ! git add .; then 667 | echo "fatal: Could not add files to track." 668 | exit 1 669 | fi 670 | 671 | git rebase --continue 672 | } 673 | 674 | # ------------------------------------------------ 675 | # USAGE/HELP ------------------------------------- 676 | # ------------------------------------------------ 677 | function _usage() 678 | { 679 | echo "usage: g [|]" 680 | echo 681 | echo "The g git aliases are:" 682 | 683 | for (( index = 1; index <= $_commands_length ; index++ )) ; do 684 | echo " "$_matches[index]"\t"$_bodies[index] 685 | done 686 | 687 | } 688 | 689 | # ------------------------------------------------ 690 | # GIT-COMMAND (GC) ------------------------------- 691 | # ------------------------------------------------ 692 | # Run a command and commit with the message of the command. 693 | # FIX: Also add gcp which pushes after. 694 | # 695 | # This should be "g x" for git execute 696 | function gc() 697 | { 698 | initial_arguments=$* 699 | 700 | # Execute all the arguments 701 | $* 702 | 703 | if [[ $? == 0 ]] ; then 704 | 705 | g_lso=`git ls-files --other --exclude-standard` 706 | 707 | if [[ -n $g_lso ]] ; then 708 | echo $g_lso 709 | 710 | if ( _prompt_success "Add these files to be tracked?" ) ; then 711 | git add . 712 | fi 713 | fi 714 | 715 | git commit --all -m $initial_arguments 716 | else 717 | echo "fatal: Command failed. Not commiting." 718 | return 1 719 | fi 720 | } 721 | 722 | # ------------------------------------------------ 723 | # MAIN/G ----------------------------------------- 724 | # ------------------------------------------------ 725 | function g() 726 | { 727 | local _g_command 728 | local _original_arguments 729 | local _found_body 730 | 731 | _g_command=$1 732 | _original_arguments=$@ 733 | 734 | # With no arguments, print g's status 735 | if [[ -z $_g_command ]] ; then 736 | git-status-display 737 | return 0 738 | fi 739 | 740 | # Check for --help 741 | if [[ $_g_command == "--help" ]] ; then 742 | _usage 743 | return 0 744 | fi 745 | 746 | # Shift to get the arguments sans "g" 747 | shift 748 | 749 | # With arguments, attempt to find the command based on the match 750 | _found_body=`_find_command $_g_command` 751 | 752 | # Command was found 753 | if [[ $? == 0 ]] ; then 754 | _echo_verbose "g: $_found_body $*" 755 | 756 | # Concatenate the found body and the quoted arguments passed to the proper 757 | # 'g' function. 758 | eval "$_found_body ${(q)@}" 759 | 760 | # Return whatever the eval returned 761 | return $? 762 | fi 763 | 764 | # Command was not found, fallback to git 765 | # FIX: Multiple args are broken 766 | _git_fallback $_original_arguments 767 | } 768 | 769 | # ------------------------------------------------ 770 | # COMPLETION ------------------------------------- 771 | # ------------------------------------------------ 772 | 773 | # Actually set the compdef to git 774 | compdef g=git 775 | 776 | #compctl -k "(ls lso lsd d cm cmp cpdm d s p cg)" g # FIX: compdef overrides these 777 | 778 | #function _g () { 779 | #local _ret=1 780 | #local cur cword prev 781 | 782 | #cur=${words[CURRENT]} 783 | #prev=${words[CURRENT-1]} 784 | #cmd=${words[2]} 785 | 786 | #let cword=CURRENT-1 787 | 788 | #emulate zsh -c _git 789 | 790 | ##case "$cmd" in 791 | ##ls) 792 | ##emulate zsh -c _git-ls-files 793 | ##;; 794 | ##g) 795 | ##emulate zsh -c _git-grep 796 | ##;; 797 | ##*) 798 | ##emulate zsh -c _git 799 | ##;; 800 | ##esac 801 | 802 | #let _ret && _default && _ret=0 803 | #return _ret 804 | #} 805 | --------------------------------------------------------------------------------