Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

first commit

  • Loading branch information...
commit 217712641ac40516762e4689fe523afa87c40c46 1 parent 5fa2c06
@orefalo authored
Showing with 3,384 additions and 3 deletions.
  1. +4 −0 .gitignore
  2. +580 −3 README.md
  3. +4 −0 cmds/g2-abort.sh
  4. +64 −0 cmds/g2-br.sh
  5. +5 −0 cmds/g2-ci.sh
  6. +17 −0 cmds/g2-co.sh
  7. +5 −0 cmds/g2-cp.sh
  8. +13 −0 cmds/g2-freeze.sh
  9. +27 −0 cmds/g2-g2am.sh
  10. +4 −0 cmds/g2-g2gc.sh
  11. +5 −0 cmds/g2-g2getremote.sh
  12. +12 −0 cmds/g2-g2isbehind.sh
  13. +11 −0 cmds/g2-g2isforced.sh
  14. +7 −0 cmds/g2-g2iswip.sh
  15. +27 −0 cmds/g2-g2pull.sh
  16. +45 −0 cmds/g2-g2push.sh
  17. +4 −0 cmds/g2-ig.sh
  18. +21 −0 cmds/g2-key.sh
  19. +5 −0 cmds/g2-lg.sh
  20. +17 −0 cmds/g2-mg.sh
  21. +12 −0 cmds/g2-panic.sh
  22. +8 −0 cmds/g2-rb.sh
  23. +10 −0 cmds/g2-rs.sh
  24. +131 −0 cmds/g2-setup.sh
  25. +7 −0 cmds/g2-sh.sh
  26. +30 −0 cmds/g2-sync.sh
  27. +12 −0 cmds/g2-track.sh
  28. +7 −0 cmds/g2-unfreeze.sh
  29. +4 −0 cmds/g2-unwip.sh
  30. +9 −0 cmds/g2-wip.sh
  31. +1,453 −0 g2-completion.sh
  32. +111 −0 g2-config.sh
  33. +25 −0 g2-install.sh
  34. +79 −0 g2-prompt.conf
  35. +456 −0 g2-prompt.sh
  36. +153 −0 g2.sh
View
4 .gitignore
@@ -0,0 +1,4 @@
+.DS_Store
+*.orig
+.idea/
+
View
583 README.md
@@ -1,4 +1,581 @@
-g2
-==
-g2 is your new git command line client
+![image](http://orefalo.github.com/g2/images/G2.jpg)
+
+##Introduction
+
+I see it every day, beginners have a hard time picking up **git**. Aside from the DSCM concepts, the command line is not easy: it is aimed at people who know git.. advanced nerds, not beginners.
+
+This project is an attempt to make the git command line a friendly place: it eases the learning process by providing guidance and high level commands.
+
+###Benefits
+
+* **g2** helps setup git settings : sshkeys, username, email & tools.
+* **g2** warns before any destructive operation.
+* **g2** provides two letter acronyms for most commands.
+* **g2** provides a reduced set of commands which give guidance on what to do next.
+* **g2** enhances command line experience with TAB completion & a smart prompt.
+* **g2** warns when a branch history was changed on the server (forced pushed).
+* **g2** checks the fresheshness of the branch prior to merging.
+* **g2** enforces new commands to force developers into a clean linear history.
+* **g2** requires a clean state before rebasing, checking out, branching or merging.
+* **g2** provides guidance when it cannot perform an operation.
+* **g2** brings a number of friendly commands such as : panic, sync, freeze, wip.
+* **g2** eases branch creation.
+
+###What G2 is not
+
+* A replacement for **git**. Rather, g2 is a layer on top of git
+* A magic way to learn GIT. It will help by providing guidance but you will still need to understand how git works.
+
+##Installation
+
+**PRE-REQUISITES**:
+
+* **g2** is a layer on top of git, If you are doing a manual install, a recent version of git must be pre-installed.
+* Please backup your favorite ~/.gitconfig as g2 with recreate it from scratch.
+
+
+###Linux (RedHat/Ubuntu):
+
+Please clone the repository, edit either **/etc/bashrc**, **/etc/bash.bashrc** or **~/.bashrc** and add the following code:
+
+ [[ $PS1 && -f /path/to/g2-install.sh ]] && \
+ . /path/to/g2-install.sh
+
+###MacOS:
+
+Same as Linux, make the change in `~/.bash_profile`
+
+The software will soon be available via a [HomeBrew](http://mxcl.github.com/homebrew/) package, stay tuned.
+
+
+###Solaris (Partially tested):
+
+Add the following script to **/etc/bashrc** or **~/.bashrc** (or any other file sourcing those).
+
+ PATH=/usr/xpg4/bin:$PATH
+ export PATH
+ [[ $PS1 && -f /path/to/g2-install.sh ]] && \
+ . /path/to/g2-install.sh
+
+###Windows:
+
+Git is not a prerequisit on windows as the installer comes bundled with it.
+
+Please download the Windows native installer from [https://github.com/downloads/orefalo/g2/G2-1.7.10.1.exe](https://github.com/downloads/orefalo/g2/G2-1.7.10.1.exe).
+
+
+##How to use
+
+The project introduces the `g` alias. Taken without parameters it displays the following output.
+
+```
+$ g
+Usage:
+ abort - aborts any rebase/merge
+ am <?-f> - amends last commit with staging area
+ br <?branch> - list or create branches
+ bs - bisect
+ co <branch> - switches branch (either local/remote)
+ cp <commit> - cherry-pick
+ ci <?params...> - commit
+ clone <url> - clone a remote repository
+ df/dt <?params...> - compares files
+ fetch - synchronizes remote branches
+ freeze/unfreeze <?-m comment> <?file> - freeze/unfreeze files
+ gc - garbage collects: run fsck & gc
+ gp - grep
+ gui - launches the GUI
+ ig <file> - adds to gitignore & removes from source control
+ init <folder> - init a repository
+ key <?-gen> - displays/generates your ssh public key
+ mg <?params...> <branch> - merge
+ mt <?params...> - fixes conflicts by opening a visual mergetool
+ mv - move (rename) a file
+ lg - displays commit log
+ ls <?params...> - list files under source control
+ panic - gets you back on HEAD, cleans all untracked files
+ pull/push <?opts> <remote> <branch> - deals with other branches
+ rb <?params...> <branch> - rebase
+ rm <params...> - remove
+ rs <params...> - reset
+ rs upstream - resets branch to upstream state
+ rt <?params...> - remote
+ rv <commit> - revert
+ setup - configures user, key, editor, tools
+ sh <?-deep> - show commit contents
+ sm <?params...> - submodule
+ st <?params...> - status
+ sync - syncs working branch: fetch, rebase & push
+ tg - tag
+ track <?upstream_branch> - shows/set tracking
+ wip/unwip - save/restore work in progress to branch
+```
+
+On top of providing two letters acronyms for most git commands, **g2** has interesting features which enhance command line experience.
+
+###Setup
+
+`g setup` and `g key` are two handy commands to setup username, email, keys, editor and tooling.
+
+![image](http://orefalo.github.com/g2/images/setup.png)
+
+
+At anytime, you may display your ssh key with: `g key`
+
+```
+$ git key
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDYUTgzU9zjsdda9WBEED5bH+SVMq5bYoIxPSzop2IqUBoyyOlRdHt4dy2r/MWiB2eKQOQmPRE7SeawhFWYbCwEdi6BtEe8m4PiZd3OIRV13TlPj54Hi6Q1Ab8emEAH026L4kwef46+j0aJf/7tZzUw/uZW9Wrnf1VN+J1VlWvmYaG9JpPBuatAlTV9rhCeQ2WO39KYWVYJxH1mO0zPEpuTBojji7HYJtlS4OCKgY9mCVBPiUzzLfmrlIhZz+k5rMWv6i4tQtats23qtHEOi9GxJm4+TSGLwM89/C186CJ+8Yx0g/c2DIbVtPm2VMwUayu8wU4GfBHtOwin4cLWsvT orefalo@dummy.com
+```
+
+Should you need to regenerate the key pair, the process is equally user friendly: use `g key -gen`
+
+```
+$ git key -gen
+Regenerate SSH Key (y/n)? y
+Generating SSH keys...
+Generating public/private rsa key pair.
+/Users/orefalo/.ssh/id_rsa already exists.
+Overwrite (y/n)? y
+Your identification has been saved in /Users/orefalo/.ssh/id_rsa.
+Your public key has been saved in /Users/orefalo/.ssh/id_rsa.pub.
+The key fingerprint is:
+57:60:84:fa:0e:3b:96:12:15:2e:f3:d5:30:ce:aa:4f orefalo@yahoo.com
+The key's randomart image is:
++--[ RSA 2048]----+
+| o+ |
+| . +. . |
+| . = + . |
+| o + + .. |
+| = +S . |
+| . + .. |
+| oE= |
+| o.= . |
+| +.. |
++-----------------+
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDYUTgzU9zjsdda9WBEED5bH+SVMq5bYoIxPSzop2IqUBoyyOlRdHt4dy2r/MWiB2eKQOQmPRE7SeawhFWYbCwEdi6BtEe8m4PiZd3OIRV13TlPj54Hi6Q1Ab8emEAH026L4kwef46+j0aJf/7tZzUw/uZW9Wrnf1VN+J1VlWvmYaG9JpPBuatAlTV9rhCeQ2WO39KYWVYJxH1mO0zPEpuTBojji7HYJtlS4OCKgY9mCVBPiUzzLfmrlIhZz+k5rMWv6i4tQtats23qtHEOi9GxJm4+TSGLwM89/C186CJ+8Yx0g/c2DIbVtPm2VMwUayu8wU4GfBHtOwin4cLWsvT orefalo@yahoo.com
+```
+
+###Basic commands
+
+Git is often referenced as a content SCM, that freezes the state of a folder.
+So rather than providing a `git add` and `git rm`, **g2** introduces the `freeze` and `unfreeze` commands.
+
+Without arguments, `freeze` literally freezes the state of the workspace into the staging area. The content can later be committed with the `ci` command or unfrozen with `unfreeze`.
+
+Finally the most common git commands `g st` and `g lg` have been enhanced to display a nice colorized outputs.
+
+![image](http://orefalo.github.com/g2/images/lg.png)
+
+
+###Panic!
+
+It happened to all of us. You try a new command (like a rebase) and things didn't work as expected. "Wait a minutes, what's that blinking led light on the flight panel? Where is the manual?". Suddenly, you feel the necessity to hunt an expert advise. Bad luck he's either not available, there no-one to help you! "Damn it ! I wish I never run that command!".
+
+Believe it or not, your are Panicking…
+
+Well, here comes `g panic`
+
+
+`panic` checks out the last good state (HEAD) and removes all files not under source control, leaving a clean workspace to resume from. It's the easiest way to get you back on track and ready to work. No more cood sweats.
+
+###Tracking
+
+A **tracking branch** is a local branch that is connected to a remote branch. When you synchronize on that branch, it automatically pushes and pulls to the remote branch that it is connected with.
+
+**g2** provides a handy command to display and set tracking: `g track`
+
+![image](http://orefalo.github.com/g2/images/track.png)
+
+By default, it displays the tracking table. The command accepts a parameter to set tracking for the working branch. Say you want to track local branch _devel_ with _origin/devel_.
+Switch to the devel branch and type `g track origin/devel`
+
+
+###Branching
+
+Displaying the list of branches is achieved with the branch `g br` command. Note how it provides details not only about the local and remote branches, but also about the state of these branches when compared to the status on the server.
+
+```
+$ g br
+ gh-pages
+* master
+ remotes/origin/HEAD -> origin/master
+ remotes/origin/gh-pages
+ remotes/origin/master
+---
+gh-pages (ahead 0) | (behind 0) origin/gh-pages
+master (ahead 0) | (behind 0) origin/master
+```
+
+Give it a parameter and it will create a new branch. **g2** will prompt if you want to create a matching remote branch and setup tracking accordingly.
+
+Use checkout `d co` to switch to that branch.
+
+```
+$ g br NEW_branch
+(M=6c1fc *1) orefalo@OLIVIERS-IMAC
+$ g br
+ NEW_branch
+ gh-pages
+* master
+ remotes/origin/HEAD -> origin/master
+ remotes/origin/gh-pages
+ remotes/origin/master
+---
+gh-pages (ahead 0) | (behind 0) origin/gh-pages
+master (ahead 0) | (behind 0) origin/master
+$ g co NEW_branch
+Switched to branch 'NEW_branch'
+$
+```
+
+If you are familiar with git, this is no rocket science. There is however a hidden gem which might save you headaches going forward: **g2** is extremely strict when it comes to switching branches.
+
+You can only switch branch from a stable state. A _stable state_ means: **no modified files, no staged files**. Should you have any changes, **g2** will complain with the following message
+
+ fatal: some files were changed on this branch, either commit <ci>, <wip> or <panic>.
+
+
+
+###Working with remotes
+
+Before introducing one of the main **g2** features, let me talk about what you should **not** do.
+Look at these graphs taken from various projects on github. Note how the branches overlap...
+
+![image](http://orefalo.github.com/g2/images/h2.jpg)
+![image](http://orefalo.github.com/g2/images/h3.jpg)
+
+Looks familiar? This is unfortunately the consequence of multiple people working on the same branch. Wouldn't it be nicer to have straight lines, with segments showing only when feature branch is merged? In fact, git provides all the tooling to get around these ugly loops, but as you can see... few people know about it ;-/
+
+With **g2** however, the graphs above are not likely to happen. **g2** enforces two different scenarios, each backed by a different command.
+
+First the scenarios:
+
+1. Saving your code into its working branch
+2. Merging features from other branches: As the project evolves other features may need to be merged in.
+
+The matching commands are `g sync` and `g pull`, here is how to use them:
+
+* Use `g sync` to synchronize the current branch. The command doesn't take any parameters because it uses the tracking table to figure the remote/branch. To enforce a clean linear history, the changes are always appended to the end of the branch. Once completed, the changes are sent back to the server.
+
+For the git expert, the command issues a _fetch, a rebase and a push_ with a multitude of validation in between. For instance, it will stop if the remote history was changed; also it won't push a wip commit (see below).
+
+* Use `g pull` when merging contents from a feature branches.
+
+
+###History changes
+
+**g2** is not permissive when it comes to switching branches, amending or rebasing.
+ Unless given the `-f` flag, it will block any attempts untill the workspace is in a "clean" state.
+
+You can easily get to a clean state by using `g panic`
+
+###Work in progress
+
+When developing, saving the _work in progress_ is common. How many times do you have to switch branch to troubleshoot another issue?
+
+git _stash_ typically comes to the rescue in that situation. But unless you provide a well detailed comment (which nobody does!), you loose track of which branches the stash applied to.
+
+That's why **g2** introduces `wip` and `unwip`. Two handy commands that you will learn to love. See below and note how a wip commit is created on your current branch.
+
+```
+$ g st
+## master
+MM README.md
+M g2-prompt.sh
+(M=000f0 +2 *1) orefalo@OLIVIERS-IMAC
+$ g wip
+[master 0dcbfb3] wip
+ 2 files changed, 31 insertions(+), 13 deletions(-)
+(M=0dcbf) orefalo@OLIVIERS-IMAC
+$ g lg
+* 0dcbfb3 - (HEAD, master) wip (5 seconds ago) <Olivier Refalo>
+* 000f060 - (origin/master, origin/HEAD) fix freeze and wip (5 hours ago) <Olivier Refalo>
+* b44487e - adding gui & freeze -m (6 hours ago) <Olivier Refalo>
+* 7acd770 - documentation, removed undo (24 hours ago) <Olivier Refalo>
+* a248217 - first commit (3 days ago) <Olivier Refalo>
+* 5fa2c06 - initial commit (3 days ago) <Olivier Refalo>
+$ g unwip
+Unstaged changes after reset:
+M README.md
+M g2-prompt.sh
+$
+```
+
+But how good is a wip commit if it behaves just like any other commit? The point is, it's not a regular commit:
+
+* A wip commit **CANNOT** be **merged, pulled, pushed or synched**. You **cannot commit** on top of it either. It's a real "work in progress" that is meant to be `unwip` at some point.
+
+
+#List of Commands
+
+### abort
+
+Aborts either a rebase or a merge.
+
+### am (?-f)
+
+Amends last commit with contents from the staging area.
+Won't amend if top commit was pushed unless the `-f` flag is given.
+
+### br <?branch>
+
+Displays the list of branches, local and remote.
+Can create new branches if given a branch name.
+
+### bs / bisect
+
+One of git best tool: `bisect`
+
+### clone (url)
+
+Clones a remote repository, wires to `git clone`
+
+### co/checkout (branch)
+
+Switches branch (either local/remote)
+extremely strict - won't let you checkout if you have changes or untracked files
+
+### cp/cherry-pick (commit)
+
+Cherry picks a commit from another branch, same as `git cherry-pick`
+
+### ci/commit (?params...)
+
+Commits the contents of the staging area. Won't commit on top of a WIP.
+
+### df/diff (?params…)
+
+Compares files on the console, wires to `diff`
+
+### dt/difftool (?params…)
+
+Compares files by opening the default diff GUI, wires to `difftool`
+
+### freeze (?-m msg) (?file)
+
+Takes all **modified, deleted and untracked** files to the staging area.
+You may also specify which file to stage.
+
+Note that you may also give it the file to stage.
+
+### gc
+
+Repository maintenance: prunes obsolete remote branches then a structure check `fsck` followed by a garbage collector `gc`
+
+### gp/grep
+
+Searches commits, same as `git grep`
+
+### ig (-file)
+
+Adds to gitignore & removes file from source control
+
+### init (-folder)
+
+Creates a local repository, wires to `git init`
+
+### key (?-gen)
+
+Displays the public ssh key.
+Give it the `--gen` flag and it will generate a new key.
+
+### mg/merge (?params...) (branch)
+
+Merges branches, same as `git merge`
+
+### mt/mergetool (?params...)
+
+Fixes conflicts by opening a visual mergetool
+
+### mv
+
+Moves (renames) a file under source control. same as `git mv`
+
+### lg/log
+
+By default, displays commit log in a pretty colorized format. Any extra parameter wires to to `git log`.
+
+```
+$ git lg
+* adbd444 - docs wording improvement pass (3 days ago) <David Greenspan>
+* 2edb152 - make tests work in IE 6-10, MobileSafari (3 days ago) <David Greenspan>
+* 7a05b13 - Merge pull request #64 from skalb/devel (3 days ago) <matt debergalis>
+|\
+| * 9ebb67a - Function passed to Meteor.ui.render must return a string. (3 days ago) <Sameer Kalburgi>
+* | e2eadee - Use correct variable name when logging a less error (3 days ago) <Josh McArthur>
+* | 32266f5 - Merge pull request #62 from milesmatthias/docupdate (3 days ago) <matt debergalis>
+|\ \
+| * | 6d57f14 - Added a note about how to read the docs locally, since it took me a while to figure out how to do it. (8 days ago) <Miles Matthias>
+* | | d28ed89 - This is allow any user added script in their header to be able to use the libraries in Meteor. For example including a plugin would have to be always written a
+* | | 7d269cd - Merge branch 'http' into devel (3 days ago) <Nick Martin>
+|\ \ \
+| * | | cde4a4a - (origin/http) First pass at HTTP docs. (3 days ago) <David Greenspan>
+| * | | 0f2673f - initial commit of HTTP package (4 days ago) <David Greenspan>
+|/ / /
+* | | e1a557f - Merge branch 'test-fixups' into devel (4 days ago) <Nick Martin>
+|\ \ \
+| * | | d7fe7c9 - have test driver report FAIL if exception anywhere (4 days ago) <David Greenspan>
+| * | | e68f9d1 - Remove old busted selenium tests, and move cli tests out of the way. (4 days ago) <Nick Martin>
+| * | | b3bdb87 - async_multi: catch exceptions in expect, prevent multi-fail (4 days ago) <David Greenspan>
+```
+
+### ls/ls-files (?params…)
+
+List files under source control, wires to `git ls-files`
+
+### panic
+
+Lost, confused? Can't figure what state you are in? Use `panic`!
+
+`panic` will checkout the latest stable state (HEAD) and remove all file not under source control, leaving a fresh clean workspace.
+
+### pull (?opts) (remote) (branch)
+
+Merges another branch with the current.
+Please use `sync` to synchronize your local branch.
+
+### push (?-f) (?opts) (remote) (branch)
+
+Sends commits to a remote git repository/branch
+
+### rb/rebase (?params…) (branch)
+
+Rebases the branch, same as `git rb`
+
+### rm (params…)
+
+Removes a file from source control, same as `git rm`
+
+### rs/reset (params…)
+
+Resets the branch to a different state. same as `git reset`
+
+`$ g rs upstream`
+
+### rt/remote (?params…)
+
+Used to add/remove remotes, same as `git remote`
+
+### rv/revert (commit)
+
+Reverts a commit, same as `git revert`
+
+### setup
+
+Configures user, key, editor & tools by prompting the user.
+
+### sh/show (?-deep) (?commit)
+
+Shows details about the given commit, defaults to HEAD
+When `-deep` is given, shows the diff.
+
+### st/status (?params…)
+
+Probably the most common command: give details about what changed since last commit.
+
+```
+$ git st
+```
+
+### sm/submodule (?params…)
+
+Same as `git submodule`
+
+### sync
+
+Synchronizes the current branch with the one of the server.
+syncs working branch: fetch, pull-rebase & push
+
+### tg/tag
+
+Tags a state, wires to `git tag`
+
+### track (?upstream_branch)
+
+Gives information about the tracking table. This table is very important: it tells how local/remote branches are interconnected.
+
+```
+$ g track
+local: master <--sync--> remote: origin/master
+--Remotes---
+origin git@github.com:orefalo/g2.git (fetch)
+origin git@github.com:orefalo/g2.git (push)
+```
+
+Should you need to change the tracking, just pass the new destination as a parameter
+
+```
+$ g track origin/NEW_branch
+local: master <--sync--> remote: origin/NEW_branch
+--Remotes---
+origin git@github.com:orefalo/g2.git (fetch)
+origin git@github.com:orefalo/g2.git (push)
+```
+
+### pull
+
+won't pull on a WIP
+won't pull from the tracking branch
+Will ask to setup tracking if not set
+
+### push
+
+won't push a WIP
+won't push to the tracking branch
+Will ask to setup tracking if not set
+
+### unfreeze (?file)
+
+Unfreezes the files from the staging area back into the workspace.
+
+### unwip
+
+Unstacks a WIP from the history into the workspace.
+
+### wip
+
+Easy way to save your WIP (Work In Progress). Stacks all current changes as a commit on the history.
+
+##FAQ
+
+###Why "g2" ?
+
+* `g` is the command, and it obviously comes from **git**
+* `2` because most of the actions are two letters long.
+
+###There is no stash ?
+
+No, not for now. With commands `wip` and `unwip`, the stash brings little benefits. You can always cherry pick from one branch to another.
+
+###Is it a new git-flow ?
+
+No, **g2** doesn't enforce any branching policy.
+
+###What if my favorite command is missing?
+
+Please notify us via the project issue tracker. For the time being, please use `$GIT_EXE`
+
+##Credits
+
+Author: [Olivier Refalo](https://github.com/orefalo)
+
+* Contains a modified version of [git-prompt](http://volnitsky.com/project/git-prompt/) - Leonid Volnitsky
+* Contains a modified version of git-completion.bash - Shawn O. Pearce
+* [GUM](https://github.com/saintsjd/gum) by saintsjd. Wonder why this project feelt short on delivery.
+
+##License
+
+Distributed under the GNU General Public License, version 2.0.
+
+##TODO
+* shunit2 the project
+* some completions are not properly working - git push origin <TAB> not working ?
+* completion, rename __git to avoid conflicts
+* g mode
+* g as - aliasing
+* introduce g2 options - panic exlcudes, count files in prompt
+
+
+
+
View
4 cmds/g2-abort.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+#
+
+[[ ! $("$GIT_EXE" rev-parse --git-dir 2> /dev/null) ]] && echo "fatal: Not a Git Repository" || ("$GIT_EXE" merge --abort 2> /dev/null || "$GIT_EXE" rebase --abort 2> /dev/null)
View
64 cmds/g2-br.sh
@@ -0,0 +1,64 @@
+#!/bin/bash
+#
+
+hasDFlag() {
+ local opt
+ while getopts ":dD:" opt; do
+ case $opt in
+ d|D) echo "true"; return ;;
+ *) echo "Usage: g br <?-D> <?branch>"; exit 1;;
+ esac
+ done
+ echo "false"
+}
+
+hasChanges() {
+ [[ $("$GIT_EXE" diff --cached --numstat | wc -l) -ne 0 ]] && echo "fatal: staged changed detected, please commit <ci> or <wip> them." && exit 1
+ [[ $("$GIT_EXE" diff --numstat | wc -l) -ne 0 ]] && echo "fatal: some files were modified, either commit <ci>, <wip> or <panic>." && exit 1
+}
+
+br_status() {
+ "$GIT_EXE" for-each-ref --format="%(refname:short) %(upstream:short)" refs/heads | \
+ while read local remote
+ do
+ [[ -z $remote ]] && continue
+ "$GIT_EXE" rev-list --left-right ${local}...${remote} -- 2> /dev/null > /tmp/git_upstream_status_delta || continue
+ LEFT_AHEAD=$(grep -c "^<" /tmp/git_upstream_status_delta)
+ RIGHT_AHEAD=$(grep -c "^>" /tmp/git_upstream_status_delta)
+ echo "$local (ahead $LEFT_AHEAD) | (behind $RIGHT_AHEAD) $remote"
+ echo
+ done
+}
+
+
+if [[ $# -eq 0 ]]; then
+ "$GIT_EXE" branch -a
+ echo "-------"
+ br_status
+else
+
+ [[ $(hasDFlag "$@") = "true" ]] && { "$GIT_EXE" branch "$@"; exit $?; }
+ hasChanges
+
+ shift $(( OPTIND - 1 ))
+ branch="${1:-/}"
+
+ [[ $branch = */* ]] && echo "fatal: $branch is not a valid branch name" && exit 1
+ [[ -n $("$GIT_EXE" branch | grep "^$branch$") ]] && echo "fatal: branch $branch already exist" && exit 1
+
+ remote=$("$GIT_EXE" g2getremote)
+ [[ -n $remote ]] && {
+
+ IFS=/ read -a rmt <<< "$remote"
+ remote=${rmt[0]}
+ read -p "Would you like to create the remote $remote/$branch on the server (y/n)? " -n 1 -r
+ echo
+ [[ $REPLY == [yY]* ]] && {
+ "$GIT_EXE" branch "$branch" && "$GIT_EXE" checkout "$branch" && "$GIT_EXE" push $remote $branch && "$GIT_EXE" fetch $remote && "$GIT_EXE" track "$remote/$branch"
+ exit $?
+ }
+ }
+
+ "$GIT_EXE" branch "$branch" && "$GIT_EXE" checkout "$branch"
+ exit $?
+fi
View
5 cmds/g2-ci.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+#
+
+[[ $("$GIT_EXE" g2iswip) = "true" ]] && echo "fatal: WIP detected, please <unwip> first." && exit 1
+[[ $("$GIT_EXE" diff --cached --numstat | wc -l) -eq 0 ]] && echo "fatal: No files to commit, please <freeze> changes first." || "$GIT_EXE" commit -u "$@"
View
17 cmds/g2-co.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+
+hasChanges() {
+ [[ $("$GIT_EXE" diff --cached --numstat | wc -l) -ne 0 ]] && echo "fatal: staged changed detected, please commit <ci> or <wip> them." && exit 1
+ [[ $("$GIT_EXE" diff --numstat | wc -l) -ne 0 ]] && echo "fatal: some files were changed in this branch, either commit <ci>, <wip> or <panic>." && exit 1
+}
+
+isBranch=$("$GIT_EXE" branch -a | grep -c "$1")
+[[ $isBranch -gt 0 ]] && {
+ hasChanges
+ "$GIT_EXE" checkout "$@" && "$GIT_EXE" clean -fd;
+ exit $?;
+}
+
+"$GIT_EXE" checkout "$@"
+
View
5 cmds/g2-cp.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+#
+
+[[ $("$GIT_EXE" g2iswip) = "true" ]] && echo "fatal: Cherry Picking on a WIP commit is forbiden, please <unwip> and commit <ci>" && exit 1
+"$GIT_EXE" cherry-pick "$@"
View
13 cmds/g2-freeze.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+#
+
+[[ $1 = "-m" ]] && {
+ [[ -n $2 ]] && { msg=$2; shift 2; } || { echo "Usage: freeze -m message"; exit 1; }
+}
+( [[ -z "$@" ]] && "$GIT_EXE" add -A || "$GIT_EXE" add -A "$@" ) && {
+ [[ -n $msg ]] && {
+ [[ $("$GIT_EXE" g2iswip) = "true" ]] && echo "fatal: wip detected, please <unwip> and commit <ci>." && exit 1
+ "$GIT_EXE" commit -m "$msg" && "$GIT_EXE" status -s
+ }
+}
+exit 0
View
27 cmds/g2-g2am.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+
+error() {
+ echo "fatal: no files to amend, please <freeze> the changes to amend."
+ exit 1
+}
+
+[[ $("$GIT_EXE" diff --cached --numstat | wc -l) -eq 0 ]] && error
+
+remote=$("$GIT_EXE" g2getremote)
+if [[ -z $remote ]]; then
+ "$GIT_EXE" commit --amend -C HEAD
+else
+
+ if [[ $("$GIT_EXE" log $remote..HEAD --oneline | wc -l) -eq 0 ]]; then
+
+ if [[ $1 = "-f" ]]; then
+ read -p "warning: force amending will rewrite the branch history, please confirm (y/n)? " -n 1 -r
+ echo
+ [[ $REPLY != [yY]* ]] && exit 1
+ else error; fi
+ fi
+
+ "$GIT_EXE" commit --amend -C HEAD
+
+fi
View
4 cmds/g2-g2gc.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+#
+
+"$GIT_EXE" fetch --all -p && "$GIT_EXE" fsck && "$GIT_EXE" reflog expire --expire=now --all && "$GIT_EXE" gc --aggressive --prune=now
View
5 cmds/g2-g2getremote.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+#
+
+remote=$("$GIT_EXE" rev-parse --symbolic-full-name --abbrev-ref @{u} 2> /dev/null)
+[[ $remote == "@{u}" ]] && echo "" || echo $remote
View
12 cmds/g2-g2isbehind.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+
+local=$("$GIT_EXE" branch | grep "*" | sed "s/* //")
+remote=$1
+[[ -z $1 ]] && remote=$("$GIT_EXE" g2getremote)
+[[ -n $remote ]] && {
+ "$GIT_EXE" fetch
+ RIGHT_AHEAD=$("$GIT_EXE" rev-list --left-right ${local}...${remote} -- 2> /dev/null | grep -c "^>")
+ [[ $RIGHT_AHEAD -gt 0 ]] && echo "true" && exit
+}
+echo "false"
View
11 cmds/g2-g2isforced.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+
+remote=$1
+[[ -z $1 ]] && remote=$("$GIT_EXE" g2getremote)
+[[ -n $remote ]] && {
+ hash=$("$GIT_EXE" reflog $remote | head -1 | grep forced-update | cut -f 1 -d " ")
+ branch=$("$GIT_EXE" branch | grep "*" | sed "s/* //")
+ [[ -n $hash && $("$GIT_EXE" reflog $branch | grep $hash | grep -c reset) -eq 0 ]] && echo "true" && exit 0
+}
+echo "false"
View
7 cmds/g2-g2iswip.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+#
+
+remote=$1
+[[ -z $1 ]] && remote=$("$GIT_EXE" g2getremote)
+[[ -z $remote ]] && [[ $("$GIT_EXE" log --oneline -1 | cut -f 2 -d " " | grep -c wip) -gt 0 ]] && echo "true" && exit 0
+[[ $("$GIT_EXE" log $remote..HEAD --oneline | cut -f 2 -d " " | uniq | grep -c wip) -gt 0 ]] && echo "true" || echo "false"
View
27 cmds/g2-g2pull.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+#
+
+error() {
+ echo "fatal: use <sync> to synchronize the current branch"
+ echo "remember, <sync>hing applies to the working branch, <pull>ing applies when merging feature branches."
+ exit 1
+}
+
+n=$#;
+[[ $n -eq 0 || ${!n} = -* ]] && error
+#[[ $("$GIT_EXE" g2iswip) = "true" ]] && echo "fatal: pulling on a wip commit is forbidden, please <unwip> and commit <ci>" && exit 1
+[[ ${!n} = */* ]] && echo "Usage: pull <?opts> <remote> <branch>" && exit 1
+branch=${!n}
+let n--
+[[ n -gt 0 && ${!n} != -* ]] && rmt=${!n} || { echo "Usage: pull <remote> <branch>" && exit 1; }
+to="$rmt/$branch"
+remote=$("$GIT_EXE" g2getremote)
+if [[ -z $remote ]]; then
+ read -p "Would you like to track $to (y/n)? " -n 1 -r
+ echo
+else
+ [[ $to = $remote ]] && error
+fi
+[[ $REPLY = [yY]* ]] && "$GIT_EXE" track "$to"
+"$GIT_EXE" fetch "$rmt"
+"$GIT_EXE" mg --no-ff "$to"
View
45 cmds/g2-g2push.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+#
+
+error() {
+ echo "fatal: sorry you can't use <push> in this context, please use the <sync> command to synchronize the current branch"
+ exit 1
+}
+
+hasFFlag() {
+ local opt
+ while getopts ":f" opt; do
+ case $opt in
+ f)
+ echo "true" && return
+ ;;
+ esac
+ done
+ echo "false"
+}
+
+fflg=$( hasFFlag "$@" )
+n=$#;
+[[ $fflg = "false" && $n -eq 0 ]] && error
+[[ $("$GIT_EXE" g2iswip) = "true" ]] && echo "fatal: pushing a wip commit is forbiden, please <unwip> and commit <ci>" && exit 1
+[[ $fflg = "true" ]] && {
+ read -p "warning: you are about to force push history, please confirm (y/n)? " -n 1 -r;
+ echo
+ [[ $REPLY == [yY]* ]] && "$GIT_EXE" push "$@";
+ exit $?;
+}
+
+branch=${!n}
+[[ $branch = */* ]] && echo "Usage: push <?opts> <remote> <branch>" && exit 1
+
+let n--
+[[ $n -gt 0 && ${!n} != -* ]] && rmt=${!n} || { echo "Usage: push <?opts> <remote> <branch>" && exit 1; }
+to="$rmt/$branch"
+remote=$("$GIT_EXE" g2getremote)
+if [[ -z $remote ]]; then
+ read -p "Would you like to track $to (y/n)? " -n 1 -r
+ echo
+else
+ [[ $to = $remote ]] && error
+fi
+"$GIT_EXE" push "$@" && [[ $REPLY == [yY]* ]] && "$GIT_EXE" track $to
View
4 cmds/g2-ig.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+#
+
+[[ -z "$@" ]] && echo "usage: ignore [file]" || { ([ ! -e .gitignore ] && touch .gitignore); echo $1 >> .gitignore && echo "Ignoring file $1" && "$GIT_EXE" rm --cached "$@" > /dev/null 2>&1 && "$GIT_EXE" st; }
View
21 cmds/g2-key.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+
+gen() {
+ echo "Generating SSH keys..."
+ emailinput=$("$GIT_EXE" config --global --get user.email)
+ ssh-keygen -t rsa -P "" -C "$emailinput" -f "$HOME/.ssh/id_rsa"
+ cat "$HOME/.ssh/id_rsa.pub"
+}
+
+
+if [[ $1 != -gen ]]; then
+ [[ ! -f $HOME/.ssh/id_rsa.pub ]] && echo "fatal: SSH key not found: $HOME/.ssh/id_rsa.pub" || cat "$HOME/.ssh/id_rsa.pub"
+else
+ if [[ -f $HOME/.ssh/id_rsa.pub ]]; then
+ read -p "Regenerate SSH Key (y/n)? " -n 1 -r
+ [[ $REPLY == [yY]* ]] && (echo; gen) || echo
+ else
+ gen
+ fi
+fi
View
5 cmds/g2-lg.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+#
+
+[[ $# -eq 0 ]] && ("$GIT_EXE" log --graph --pretty=format:"%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset" --abbrev-commit --date=relative
+true;) || "$GIT_EXE" log "$@"
View
17 cmds/g2-mg.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+
+[[ $("$GIT_EXE" g2iswip) = "true" ]] && echo "fatal: merging on a wip commit is forbiden, please <unwip> and commit <ci> first..." && exit 1
+
+[[ $("$GIT_EXE" g2isbehind) = "true" ]] && read -p "It appears the current branch is in the past, proceed with the merge (y/n)? " -n 1 -r && [[ $REPLY != [yY]* ]] && exit 0
+
+# merge returns 0 when it merges correctly
+"$GIT_EXE" merge "$@" || {
+
+ unmerged=$("$GIT_EXE" ls-files --unmerged)
+ if [[ -n $unmerged ]]; then
+ echo "info: some files need to be merged manually, please use <mt> to fix conflicts..."
+ echo " once all resolved, please <commit> the files and resume the operation. Note that you may <abort> at any time."
+ fi
+ exit 1;
+}
View
12 cmds/g2-panic.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+
+read -p "Remove all untracked files and checkout HEAD, are you sure (y/n)? " -n 1 -r
+[[ $REPLY == [yY]* ]] && {
+ echo
+ "$GIT_EXE" abort
+ "$GIT_EXE" reset --hard HEAD && "$GIT_EXE" clean -fdx
+
+ branch=$("$GIT_EXE" branch | grep "*" | sed "s/* //")
+ [[ $branch = "(no branch)" ]] && "$GIT_EXE" checkout master
+}
View
8 cmds/g2-rb.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+#
+
+#TODO: make sure we are clear
+
+read -p "The history is about to be rewritten. This might be a dangerous operation, please confirm (y/n)? " -n 1 -r
+echo
+[[ $REPLY = [yY]* ]] && "$GIT_EXE" rebase "$@"
View
10 cmds/g2-rs.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+#
+
+[ $1 == "upstream" ] && {
+ read -p "warning: resetting to the upstream may erase any local changes, are you sure (y/n)? " -n 1 -r
+ [[ $REPLY == [yY]* ]] && { echo
+ remote=$("$GIT_EXE" g2getremote)
+ [[ -n $remote ]] && { echo "Resetting branch to $remote" && "$GIT_EXE" reset --hard "$remote"; } || echo "fatal: please setup tracking for this branch, see <track>";
+ }
+} || "$GIT_EXE" reset "$@";
View
131 cmds/g2-setup.sh
@@ -0,0 +1,131 @@
+#!/bin/bash
+#
+
+## USER NAME
+
+nameinput=$("$GIT_EXE" config --global --get user.name)
+if [[ -z $nameinput ]]; then
+ read -p "Please input your full name: " -e nameinput
+else
+ read -p "Please input your full name ($nameinput): " -e nameinput
+fi
+[[ -n $nameinput ]] && "$GIT_EXE" config --global user.name "$nameinput"
+
+## EMAIL
+emailinput=$("$GIT_EXE" config --global --get user.email);
+if [[ -z $emailinput ]]; then
+ read -p "Please input your email: " -e emailinput
+else
+ read -p "Please input your email ($emailinput): " -e emailinput
+fi
+[[ -n "$emailinput" ]] && "$GIT_EXE" config --global user.email "$emailinput"
+
+## EDITOR
+editor=$("$GIT_EXE" config --global --get core.editor)
+if [[ -z "$editor" ]]; then
+ read -p "Please input your editor: " -e editor
+else
+ read -p "Please input your editor ($editor): " -e editor
+fi
+[[ -n "$editor" ]] && "$GIT_EXE" config --global core.editor "$editor"
+
+
+## MERGETOOL
+mt_alias=$("$GIT_EXE" config merge.tool)
+mergetools="araxis bc3 diffuse ecmerge emerge gvimdiff kdiff3 meld opendiff p4merge kdiff tortoisemerge vimdiff xxdiff CUSTOM"
+
+PS3="What is the favorite merge tool ($mt_alias) ? "
+
+select choice in $mergetools; do
+if [[ -n $choice ]]; then
+ if [[ $choice = "CUSTOM" ]]; then
+ if [[ -z $mt_alias ]]; then
+ read -p "Please input the mergetool alias: " -e mt_alias
+ else
+ read -p "Please input the mergetool alias ($mt_alias): " -e mt_alias
+ fi
+ [[ -z $mt_alias ]] && echo "The merge tool cannot be left blank, please make a selection..." && continue
+ "$GIT_EXE" config --global merge.tool "$mt_alias"
+
+
+ cmdLine=$("$GIT_EXE" config mergetool.${mt_alias}.cmd)
+ if [[ -z $cmdLine ]]; then
+ read -p "Please provide the command to call : " -e cmdLine
+ else
+ read -p "Command to call ($cmdLine): " -e cmdLine
+ fi
+ if [[ -z $cmdLine ]]; then
+ "$GIT_EXE" config --global --unset mergetool.${mt_alias}.cmd
+ else
+ "$GIT_EXE" config --global mergetool.${mt_alias}.cmd "$cmdLine"
+ fi
+ else
+ mt_alias=$choice
+ echo "Merge tool set to $mt_alias, please make sure to include the application(s) in the PATH"
+ "$GIT_EXE" config --global merge.tool "${mt_alias}"
+ "$GIT_EXE" config --global --unset mergetool.${mt_alias}.cmd
+ fi
+ break
+
+else
+ echo "Invalid entry, please try again.\n"
+fi
+done
+
+existCode=$("$GIT_EXE" config mergetool.${mt_alias}.trustExitCode)
+if [[ -z $existCode ]]; then
+ read -p "Trust $mt_alias exit code? (false) " -e existCode
+else
+ read -p "Trust $mt_alias exit code? ($existCode): " -e existCode
+fi
+[[ -z $existCode ]] && exitCode=false
+"$GIT_EXE" config --global mergetool.${mt_alias}.trustExitCode $existCode
+
+
+
+## DIFFTOOL
+
+dt_alias=$("$GIT_EXE" config diff.tool)
+difftools="araxis bc3 diffuse emerge ecmerge gvimdiff kdiff3 kompare meld opendiff p4merge tkdiff vimdiff xxdiff CUSTOM"
+
+
+PS3="What is the favorite diff tool ($dt_alias) ? "
+
+select choice in $difftools; do
+if [[ -n $choice ]]; then
+ if [[ $choice = "CUSTOM" ]]; then
+ if [[ -z $dt_alias ]]; then
+ read -p "Please input the difftool alias: " -e dt_alias;
+ else
+ read -p "Please input the difftool alias ($dt_alias): " -e dt_alias;
+ fi
+ [[ -z $dt_alias ]] && echo "The difftool cannot be left blank, please make a selection..." && continue;
+ "$GIT_EXE" config --global diff.tool "$dt_alias"
+
+
+ cmdLine=$("$GIT_EXE" config difftool.${dt_alias}.cmd)
+ if [[ -z $cmdLine ]]; then
+ read -p "Please provide the command to call : " -e cmdLine;
+ else
+ read -p "Command to call ($cmdLine): " -e cmdLine;
+ fi
+ if [[ -z $cmdLine ]]; then
+ "$GIT_EXE" config --global --unset difftool.${dt_alias}.cmd
+ else
+ "$GIT_EXE" config --global difftool.${dt_alias}.cmd "$cmdLine"
+ fi
+ else
+ dt_alias=$choice
+ echo "Merge tool set to $dt_alias, please make sure to include the application(s) in the PATH"
+ "$GIT_EXE" config --global diff.tool "${dt_alias}"
+ "$GIT_EXE" config --global --unset difftool.${dt_alias}.cmd
+ fi
+ break
+
+else
+ echo "Invalid entry, please try again.\n"
+fi
+done
+
+## SSH KEY
+"$GIT_EXE" key -gen
View
7 cmds/g2-sh.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+#
+
+[[ $1 == "-deep" ]] && shift || flag="--name-only"
+[[ -z $1 ]] && br="HEAD" || br=$1
+[[ -n $flag ]] && { "$GIT_EXE" show --pretty="format:" $flag $br | sort | uniq; } || "$GIT_EXE" show $br;
+
View
30 cmds/g2-sync.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+
+[[ $# -gt 0 ]] && echo "Usage: <sync>" && echo "Remember, <sync>hing applies to the working branch, when <pull>ing applies when merging feature branches" && exit 1
+
+remote=$("$GIT_EXE" g2getremote)
+
+[[ $("$GIT_EXE" g2iswip $remote) = "true" ]] && echo "fatal: sorry, wip commits shall not be synced. Please <unwip>, then <freeze> & commit <ci>" && exit 1;
+[[ -z $remote ]] && echo "fatal: please use <track> to setup the remote/branch to track with" && exit 2
+[[ $# -ne 0 ]] && echo "fatal: sorry, you may only <sync> against the tracking remote/branch, use <pull> or <push> to deal with other branches." && exit 3
+"$GIT_EXE" fetch || exit $?;
+[[ $("$GIT_EXE" g2isforced $remote) = "true" ]] && \
+ echo "abort: it appears the history of the branch was changed on the server." \
+ echo " please issue a <rs upstream> or a <rb $remote> to resume" \
+ exit 1;
+branch=$("$GIT_EXE" branch | grep "*" | sed "s/* //")
+"$GIT_EXE" rev-list --left-right $branch...$remote -- 2> /dev/null > /tmp/git_upstream_status_delta || exit $?
+lchg=$(grep -c "^<" /tmp/git_upstream_status_delta);
+rchg=$(grep -c "^>" /tmp/git_upstream_status_delta);
+[[ $rchg -gt 0 ]] && { "$GIT_EXE" rebase $remote || {
+ unmerged=$("$GIT_EXE" ls-files --unmerged)
+ if [[ -n $unmerged ]]; then
+ echo "info: some files need to be merged manually, please use <mt> to fix conflicts..."
+ echo " Once all resolved, use <rb --continue> to resume. note that you may <abort> at any time"
+ fi
+ exit 1;
+ }
+}
+[[ $lchg -gt 0 ]] && { "$GIT_EXE" push || exit $?; }
+exit 0;
View
12 cmds/g2-track.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+#
+
+if [[ $# -eq 1 ]]; then
+ [[ $1 != */* ]] && echo "fatal: $1 is not an upstream branch (ie. origin/xxx)." && exit 1
+ branch=$("$GIT_EXE" branch | grep "*" | sed "s/* //")
+ "$GIT_EXE" branch --set-upstream $branch $1
+else
+ "$GIT_EXE" for-each-ref --format="local: %(refname:short) <--sync--> remote: %(upstream:short)" refs/heads
+ echo "--Remotes------"
+ "$GIT_EXE" remote -v
+fi
View
7 cmds/g2-unfreeze.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+#
+
+([[ -z "$@" ]] && ("$GIT_EXE" reset -q HEAD > /dev/null || echo "fatal: first commit must be unfrozen file by file.") || ("$GIT_EXE" reset -q HEAD -- $@ > /dev/null || "$GIT_EXE" rm -q --cached $@))
+
+"$GIT_EXE" status -s;
+
View
4 cmds/g2-unwip.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+#
+
+[[ $("$GIT_EXE" g2iswip) = "false" ]] && echo "fatal: there is nothing to <unwip>..." || ("$GIT_EXE" log -n 1 | grep -q -c wip && "$GIT_EXE" reset HEAD~1)
View
9 cmds/g2-wip.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+#
+
+if [[ $("$GIT_EXE" g2iswip) = "true" ]]; then
+ echo "info: amending previous wip commit..."
+ "$GIT_EXE" g2am
+else
+ "$GIT_EXE" freeze -m wip
+fi
View
1,453 g2-completion.sh
@@ -0,0 +1,1453 @@
+#!/bin/bash
+#
+# bash/zsh completion support for core Git.
+#
+# Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
+# Conceptually based on gitcompletion (http://gitweb.hawaga.org.uk/).
+# Distributed under the GNU General Public License, version 2.0.
+#
+
+if [[ -n ${ZSH_VERSION-} ]]; then
+ autoload -U +X bashcompinit && bashcompinit
+fi
+
+case "$COMP_WORDBREAKS" in
+*:*) : great ;;
+*) COMP_WORDBREAKS="$COMP_WORDBREAKS:"
+esac
+
+# __gitdir accepts 0 or 1 arguments (i.e., location)
+# returns location of .git repo
+__gitdir ()
+{
+ if [ -z "${1-}" ]; then
+ if [ -n "${__git_dir-}" ]; then
+ echo "$__git_dir"
+ elif [ -d .git ]; then
+ echo .git
+ else
+ "$GIT_EXE" rev-parse --git-dir 2>/dev/null
+ fi
+ elif [ -d "$1/.git" ]; then
+ echo "$1/.git"
+ else
+ echo "$1"
+ fi
+}
+
+# __gitcomp_1 requires 2 arguments
+__gitcomp_1 ()
+{
+ local c IFS=$' \t\n'
+ for c in $1; do
+ c="$c$2"
+ case $c in
+ --*=*|*.) ;;
+ *) c="$c " ;;
+ esac
+ printf '%s\n' "$c"
+ done
+}
+
+# The following function is based on code from:
+#
+# bash_completion - programmable completion functions for bash 3.2+
+#
+# Copyright © 2006-2008, Ian Macdonald <ian@caliban.org>
+# © 2009-2010, Bash Completion Maintainers
+# <bash-completion-devel@lists.alioth.debian.org>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The latest version of this software can be obtained here:
+#
+# http://bash-completion.alioth.debian.org/
+#
+# RELEASE: 2.x
+
+# This function can be used to access a tokenized list of words
+# on the command line:
+#
+# __git_reassemble_comp_words_by_ref '=:'
+# if test "${words_[cword_-1]}" = -w
+# then
+# ...
+# fi
+#
+# The argument should be a collection of characters from the list of
+# word completion separators (COMP_WORDBREAKS) to treat as ordinary
+# characters.
+#
+# This is roughly equivalent to going back in time and setting
+# COMP_WORDBREAKS to exclude those characters. The intent is to
+# make option types like --date=<type> and <rev>:<path> easy to
+# recognize by treating each shell word as a single token.
+#
+# It is best not to set COMP_WORDBREAKS directly because the value is
+# shared with other completion scripts. By the time the completion
+# function gets called, COMP_WORDS has already been populated so local
+# changes to COMP_WORDBREAKS have no effect.
+#
+# Output: words_, cword_, cur_.
+
+__git_reassemble_comp_words_by_ref()
+{
+ local exclude i j first
+ # Which word separators to exclude?
+ exclude="${1//[^$COMP_WORDBREAKS]}"
+ cword_=$COMP_CWORD
+ if [ -z "$exclude" ]; then
+ words_=("${COMP_WORDS[@]}")
+ return
+ fi
+ # List of word completion separators has shrunk;
+ # re-assemble words to complete.
+ for ((i=0, j=0; i < ${#COMP_WORDS[@]}; i++, j++)); do
+ # Append each nonempty word consisting of just
+ # word separator characters to the current word.
+ first=t
+ while
+ [ $i -gt 0 ] &&
+ [ -n "${COMP_WORDS[$i]}" ] &&
+ # word consists of excluded word separators
+ [ "${COMP_WORDS[$i]//[^$exclude]}" = "${COMP_WORDS[$i]}" ]
+ do
+ # Attach to the previous token,
+ # unless the previous token is the command name.
+ if [ $j -ge 2 ] && [ -n "$first" ]; then
+ ((j--))
+ fi
+ first=
+ words_[$j]=${words_[j]}${COMP_WORDS[i]}
+ if [ $i = $COMP_CWORD ]; then
+ cword_=$j
+ fi
+ if (($i < ${#COMP_WORDS[@]} - 1)); then
+ ((i++))
+ else
+ # Done.
+ return
+ fi
+ done
+ words_[$j]=${words_[j]}${COMP_WORDS[i]}
+ if [ $i = $COMP_CWORD ]; then
+ cword_=$j
+ fi
+ done
+}
+
+if ! type _get_comp_words_by_ref >/dev/null 2>&1; then
+if [[ -z ${ZSH_VERSION:+set} ]]; then
+_get_comp_words_by_ref ()
+{
+ local exclude cur_ words_ cword_
+ if [ "$1" = "-n" ]; then
+ exclude=$2
+ shift 2
+ fi
+ __git_reassemble_comp_words_by_ref "$exclude"
+ cur_=${words_[cword_]}
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ cur)
+ cur=$cur_
+ ;;
+ prev)
+ prev=${words_[$cword_-1]}
+ ;;
+ words)
+ words=("${words_[@]}")
+ ;;
+ cword)
+ cword=$cword_
+ ;;
+ esac
+ shift
+ done
+}
+else
+_get_comp_words_by_ref ()
+{
+ while [ $# -gt 0 ]; do
+ case "$1" in
+ cur)
+ cur=${COMP_WORDS[COMP_CWORD]}
+ ;;
+ prev)
+ prev=${COMP_WORDS[COMP_CWORD-1]}
+ ;;
+ words)
+ words=("${COMP_WORDS[@]}")
+ ;;
+ cword)
+ cword=$COMP_CWORD
+ ;;
+ -n)
+ # assume COMP_WORDBREAKS is already set sanely
+ shift
+ ;;
+ esac
+ shift
+ done
+}
+fi
+fi
+
+# Generates completion reply with compgen, appending a space to possible
+# completion words, if necessary.
+# It accepts 1 to 4 arguments:
+# 1: List of possible completion words.
+# 2: A prefix to be added to each possible completion word (optional).
+# 3: Generate possible completion matches for this word (optional).
+# 4: A suffix to be appended to each possible completion word (optional).
+__gitcomp ()
+{
+ local cur_="${3-$cur}"
+
+ case "$cur_" in
+ --*=)
+ COMPREPLY=()
+ ;;
+ *)
+ local IFS=$'\n'
+ COMPREPLY=($(compgen -P "${2-}" \
+ -W "$(__gitcomp_1 "${1-}" "${4-}")" \
+ -- "$cur_"))
+ ;;
+ esac
+}
+
+# Generates completion reply with compgen from newline-separated possible
+# completion words by appending a space to all of them.
+# It accepts 1 to 4 arguments:
+# 1: List of possible completion words, separated by a single newline.
+# 2: A prefix to be added to each possible completion word (optional).
+# 3: Generate possible completion matches for this word (optional).
+# 4: A suffix to be appended to each possible completion word instead of
+# the default space (optional). If specified but empty, nothing is
+# appended.
+__gitcomp_nl ()
+{
+ local IFS=$'\n'
+
+ # ZSH would quote the trailing space added with -S. bash users
+ # will appreciate the extra space to compensate the use of -o nospace.
+ if [ -n "${ZSH_VERSION-}" ] && [ "$suffix" = " " ]; then
+ suffix=""
+ fi
+
+ COMPREPLY=($(compgen -P "${2-}" -S "${4- }" -W "$1" -- "${3-$cur}"))
+}
+
+__git_heads ()
+{
+ local dir="$(__gitdir)"
+ if [ -d "$dir" ]; then
+ "$GIT_EXE" --git-dir="$dir" for-each-ref --format='%(refname:short)' \
+ refs/heads
+ return
+ fi
+}
+
+__git_tags ()
+{
+ local dir="$(__gitdir)"
+ if [ -d "$dir" ]; then
+ "$GIT_EXE" --git-dir="$dir" for-each-ref --format='%(refname:short)' \
+ refs/tags
+ return
+ fi
+}
+
+# __git_refs accepts 0, 1 (to pass to __gitdir), or 2 arguments
+# presence of 2nd argument means use the guess heuristic employed
+# by checkout for tracking branches
+__git_refs ()
+{
+ echo params- "${1-}" "${2-}" >> /tmp/debug
+
+ local i hash dir="$(__gitdir "${1-}")" track="${2-}"
+
+ echo dir - $dir >> /tmp/debug
+
+ local format refs
+ if [ -d "$dir" ]; then
+ echo $cur >> /tmp/debug
+
+ case "$cur" in
+ refs|refs/*)
+ format="refname"
+ refs="${cur%/*}"
+ track=""
+ ;;
+ *)
+ for i in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
+ if [ -e "$dir/$i" ]; then echo $i; fi
+ done
+ format="refname:short"
+ refs="refs/tags refs/heads refs/remotes"
+ ;;
+ esac
+ "$GIT_EXE" --git-dir="$dir" for-each-ref --format="%($format)" \
+ $refs
+ if [ -n "$track" ]; then
+ # employ the heuristic used by git checkout
+ # Try to find a remote branch that matches the completion word
+ # but only output if the branch name is unique
+ local ref entry
+ "$GIT_EXE" --git-dir="$dir" for-each-ref --shell --format="ref=%(refname:short)" \
+ "refs/remotes/" | \
+ while read -r entry; do
+ eval "$entry"
+ ref="${ref#*/}"
+ if [[ "$ref" == "$cur"* ]]; then
+ echo "$ref"
+ fi
+ done | uniq -u
+ fi
+ return
+ fi
+ case "$cur" in
+ refs|refs/*)
+ "$GIT_EXE" ls-remote "$dir" "$cur*" 2>/dev/null | \
+ while read -r hash i; do
+ case "$i" in
+ *^{}) ;;
+ *) echo "$i" ;;
+ esac
+ done
+ ;;
+ *)
+ "$GIT_EXE" ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
+ while read -r hash i; do
+ case "$i" in
+ *^{}) ;;
+ refs/*) echo "${i#refs/*/}" ;;
+ *) echo "$i" ;;
+ esac
+ done
+ ;;
+ esac
+}
+
+# __git_refs2 requires 1 argument (to pass to __git_refs)
+__git_refs2 ()
+{
+ local i
+ for i in $(__git_refs "$1"); do
+ echo "$i:$i"
+ done
+}
+
+# __git_refs_remotes requires 1 argument (to pass to ls-remote)
+__git_refs_remotes ()
+{
+ local i hash
+ "$GIT_EXE" ls-remote "$1" 'refs/heads/*' 2>/dev/null | \
+ while read -r hash i; do
+ echo "$i:refs/remotes/$1/${i#refs/heads/}"
+ done
+}
+
+__git_remotes ()
+{
+ local i IFS=$'\n' d="$(__gitdir)"
+ test -d "$d/remotes" && ls -1 "$d/remotes"
+ for i in $("$GIT_EXE" --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do
+ i="${i#remote.}"
+ echo "${i/.url*/}"
+ done
+}
+
+__git_list_merge_strategies ()
+{
+ "$GIT_EXE" merge -s help 2>&1 |
+ sed -n -e '/[Aa]vailable strategies are: /,/^$/{
+ s/\.$//
+ s/.*://
+ s/^[ ]*//
+ s/[ ]*$//
+ p
+ }'
+}
+
+__git_merge_strategies=
+# 'git merge -s help' (and thus detection of the merge strategy
+# list) fails, unfortunately, if run outside of any git working
+# tree. __git_merge_strategies is set to the empty string in
+# that case, and the detection will be repeated the next time it
+# is needed.
+__git_compute_merge_strategies ()
+{
+ test -n "$__git_merge_strategies" ||
+ __git_merge_strategies=$(__git_list_merge_strategies)
+}
+
+__git_complete_revlist_file ()
+{
+ local pfx ls ref cur_="$cur"
+ case "$cur_" in
+ *..?*:*)
+ return
+ ;;
+ ?*:*)
+ ref="${cur_%%:*}"
+ cur_="${cur_#*:}"
+ case "$cur_" in
+ ?*/*)
+ pfx="${cur_%/*}"
+ cur_="${cur_##*/}"
+ ls="$ref:$pfx"
+ pfx="$pfx/"
+ ;;
+ *)
+ ls="$ref"
+ ;;
+ esac
+
+ case "$COMP_WORDBREAKS" in
+ *:*) : great ;;
+ *) pfx="$ref:$pfx" ;;
+ esac
+
+ local IFS=$'\n'
+ COMPREPLY=($(compgen -P "$pfx" \
+ -W "$("$GIT_EXE" --git-dir="$(__gitdir)" ls-tree "$ls" \
+ | sed '/^100... blob /{
+ s,^.* ,,
+ s,$, ,
+ }
+ /^120000 blob /{
+ s,^.* ,,
+ s,$, ,
+ }
+ /^040000 tree /{
+ s,^.* ,,
+ s,$,/,
+ }
+ s/^.* //')" \
+ -- "$cur_"))
+ ;;
+ *...*)
+ pfx="${cur_%...*}..."
+ cur_="${cur_#*...}"
+ __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+ ;;
+ *..*)
+ pfx="${cur_%..*}.."
+ cur_="${cur_#*..}"
+ __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+ ;;
+ *)
+ __gitcomp_nl "$(__git_refs)"
+ ;;
+ esac
+}
+
+
+__git_complete_file ()
+{
+ __git_complete_revlist_file
+}
+
+__git_complete_revlist ()
+{
+ __git_complete_revlist_file
+}
+
+__git_complete_remote_or_refspec ()
+{
+ local cur_="$cur" cmd="${words[1]}"
+ local i c=2 remote="" pfx="" lhs=1 no_complete_refspec=0
+ echo $cmd >> /tmp/debug
+ if [ "$cmd" = "remote" ]; then
+ ((c++))
+ fi
+ while [ $c -lt $cword ]; do
+ i="${words[c]}"
+ case "$i" in
+ --mirror) [ "$cmd" = "push" ] && no_complete_refspec=1 ;;
+ --all)
+ case "$cmd" in
+ push) no_complete_refspec=1 ;;
+ fetch)
+ COMPREPLY=()
+ return
+ ;;
+ *) ;;
+ esac
+ ;;
+ -*) ;;
+ *) remote="$i"; break ;;
+ esac
+ ((c++))
+ done
+ if [ -z "$remote" ]; then
+ __gitcomp_nl "$(__git_remotes)"
+ return
+ fi
+ if [ $no_complete_refspec = 1 ]; then
+ COMPREPLY=()
+ return
+ fi
+ [ "$remote" = "." ] && remote=
+ case "$cur_" in
+ *:*)
+ case "$COMP_WORDBREAKS" in
+ *:*) : great ;;
+ *) pfx="${cur_%%:*}:" ;;
+ esac
+ cur_="${cur_#*:}"
+ lhs=0
+ ;;
+ +*)
+ pfx="+"
+ cur_="${cur_#+}"
+ ;;
+ esac
+ echo cmd $cmd >> /tmp/debug
+ echo lhs $lhs >> /tmp/debug
+ echo pfx "$pfx" >> /tmp/debug
+ echo cur_ $cur_ >> /tmp/debug
+ echo remote $remote >> /tmp/debug
+ case "$cmd" in
+ fetch)
+ if [ $lhs = 1 ]; then
+ __gitcomp_nl "$(__git_refs2 "$remote")" "$pfx" "$cur_"
+ else
+ __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+ fi
+ ;;
+ pull|rt|remote)
+ echo pull case >> /tmp/debug
+ if [ $lhs = 1 ]; then
+ __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+ else
+ __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+ fi
+ ;;
+ push)
+ if [ $lhs = 1 ]; then
+ __gitcomp_nl "$(__git_refs)" "$pfx" "$cur_"
+ else
+ __gitcomp_nl "$(__git_refs "$remote")" "$pfx" "$cur_"
+ fi
+ ;;
+ esac
+}
+
+__git_complete_strategy ()
+{
+ __git_compute_merge_strategies
+ case "$prev" in
+ -s|--strategy)
+ __gitcomp "$__git_merge_strategies"
+ return 0
+ esac
+ case "$cur" in
+ --strategy=*)
+ __gitcomp "$__git_merge_strategies" "" "${cur##--strategy=}"
+ return 0
+ ;;
+ esac
+ return 1
+}
+
+__git_list_all_commands ()
+{
+ echo "abort am br branch bs bisect clone co checkout cp cherry-pick ci commit df diff dt difftool fetch freeze key gc gp grep gui ig init mg merge mt mergetool mv lg log ls panic pull push rb rebase rm rs reset rt remote rv revert setup sh show sm submodule st status sync tg tag track unfreeze unwip wip"
+}
+
+__git_all_commands=
+__git_compute_all_commands ()
+{
+ test -n "$__git_all_commands" ||
+ __git_all_commands=$(__git_list_all_commands)
+}
+
+__git_pretty_aliases ()
+{
+ local i IFS=$'\n'
+ for i in $("$GIT_EXE" --git-dir="$(__gitdir)" config --get-regexp "pretty\..*" 2>/dev/null); do
+ case "$i" in
+ pretty.*)
+ i="${i#pretty.}"
+ echo "${i/ */}"
+ ;;
+ esac
+ done
+}
+
+# __git_find_on_cmdline requires 1 argument
+__git_find_on_cmdline ()
+{
+ local word subcommand c=1
+ while [ $c -lt $cword ]; do
+ word="${words[c]}"
+ for subcommand in $1; do
+ if [ "$subcommand" = "$word" ]; then
+ echo "$subcommand"
+ return
+ fi
+ done
+ ((c++))
+ done
+}
+
+__git_has_doubledash ()
+{
+ local c=1
+ while [ $c -lt $cword ]; do
+ if [ "--" = "${words[c]}" ]; then
+ return 0
+ fi
+ ((c++))
+ done
+ return 1
+}
+
+__git_whitespacelist="nowarn warn error error-all fix"
+
+_git_am ()
+{
+ case "$cur" in
+ -*)
+ __gitcomp "-f"
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+}
+
+
+_git_bs ()
+{
+ __git_has_doubledash && return
+
+ local subcommands="start bad good skip reset visualize replay log run"
+ local subcommand="$(__git_find_on_cmdline "$subcommands")"
+ if [ -z "$subcommand" ]; then
+ if [ -f "$(__gitdir)"/BISECT_START ]; then
+ __gitcomp "$subcommands"
+ else
+ __gitcomp "replay start"
+ fi
+ return
+ fi
+
+ case "$subcommand" in
+ bad|good|reset|skip|start)
+ __gitcomp_nl "$(__git_refs)"
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+}
+
+_git_bisect ()
+{
+ _git_bs
+}
+
+_git_br ()
+{
+ local i c=1 only_local_ref="n" has_r="n"
+
+ while [ $c -lt $cword ]; do
+ i="${words[c]}"
+ case "$i" in
+ -d|-m) only_local_ref="y" ;;
+ -r) has_r="y" ;;
+ esac
+ ((c++))
+ done
+
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --color --no-color --verbose --abbrev= --no-abbrev
+ --track --no-track --contains --merged --no-merged
+ --set-upstream --edit-description --list
+ "
+ ;;
+ *)
+ if [ $only_local_ref = "y" -a $has_r = "n" ]; then
+ __gitcomp_nl "$(__git_heads)"
+ else
+ __gitcomp_nl "$(__git_refs)"
+ fi
+ ;;
+ esac
+}
+
+_git_branch()
+{
+ _git_br
+}
+
+_git_co ()
+{
+ __git_has_doubledash && return
+
+ case "$cur" in
+ --conflict=*)
+ __gitcomp "diff3 merge" "" "${cur##--conflict=}"
+ ;;
+ --*)
+ __gitcomp "
+ --quiet --ours --theirs --track --no-track --merge
+ --conflict= --orphan --patch
+ "
+ ;;
+ *)
+ # check if --track, --no-track, or --no-guess was specified
+ # if so, disable DWIM mode
+ local flags="--track --no-track --no-guess" track=1
+ if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
+ track=''
+ fi
+ __gitcomp_nl "$(__git_refs '' $track)"
+ ;;
+ esac
+}
+
+_git_checkout()
+{
+ _git_co
+}
+
+_git_cp ()
+{
+ case "$cur" in
+ --*)
+ __gitcomp "--edit --no-commit"
+ ;;
+ *)
+ __gitcomp_nl "$(__git_refs)"
+ ;;
+ esac
+}
+
+_git_cherry_pick ()
+{
+ _git_cp
+}
+
+_git_clone ()
+{
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --local
+ --no-hardlinks
+ --shared
+ --reference
+ --quiet
+ --no-checkout
+ --bare
+ --mirror
+ --origin
+ --upload-pack
+ --template=
+ --depth
+ "
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
+_git_ci ()
+{
+ __git_has_doubledash && return
+
+ case "$cur" in
+ --cleanup=*)
+ __gitcomp "default strip verbatim whitespace
+ " "" "${cur##--cleanup=}"
+ return
+ ;;
+ --reuse-message=*|--reedit-message=*|\
+ --fixup=*|--squash=*)
+ __gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
+ return
+ ;;
+ --untracked-files=*)
+ __gitcomp "all no normal" "" "${cur##--untracked-files=}"
+ return
+ ;;
+ --*)
+ __gitcomp "
+ --all --author= --signoff --verify --no-verify
+ --edit --amend --include --only --interactive
+ --dry-run --reuse-message= --reedit-message=
+ --reset-author --file= --message= --template=
+ --cleanup= --untracked-files --untracked-files=
+ --verbose --quiet --fixup= --squash=
+ "
+ return
+ esac
+ COMPREPLY=()
+}
+
+_git_commit ()
+{
+ _git_ci
+}
+
+__git_diff_common_options="--stat --numstat --shortstat --summary
+ --patch-with-stat --name-only --name-status --color
+ --no-color --color-words --no-renames --check
+ --full-index --binary --abbrev --diff-filter=
+ --find-copies-harder
+ --text --ignore-space-at-eol --ignore-space-change
+ --ignore-all-space --exit-code --quiet --ext-diff
+ --no-ext-diff
+ --no-prefix --src-prefix= --dst-prefix=
+ --inter-hunk-context=
+ --patience
+ --raw
+ --dirstat --dirstat= --dirstat-by-file
+ --dirstat-by-file= --cumulative
+"
+
+_git_df ()
+{
+ __git_has_doubledash && return
+
+ case "$cur" in
+ --*)
+ __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
+ --base --ours --theirs --no-index
+ $__git_diff_common_options
+ "
+ return
+ ;;
+ esac
+ __git_complete_revlist_file
+}
+
+_git_diff () {
+ _git_df
+}
+
+__git_mergetools_common="diffuse ecmerge emerge kdiff3 meld opendiff
+ tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3
+"
+
+_git_dt ()
+{
+ __git_has_doubledash && return
+
+ case "$cur" in
+ --tool=*)
+ __gitcomp "$__git_mergetools_common kompare" "" "${cur##--tool=}"
+ return
+ ;;
+ --*)
+ __gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
+ --base --ours --theirs
+ --no-renames --diff-filter= --find-copies-harder
+ --relative --ignore-submodules
+ --tool="
+ return
+ ;;
+ esac
+ __git_complete_file
+}
+
+_git_difftool () {
+ _git_dt
+}
+
+__git_fetch_options="
+ --quiet --verbose --append --upload-pack --force --keep --depth=
+ --tags --no-tags --all --prune --dry-run
+"
+
+_git_fetch ()
+{
+ case "$cur" in
+ --*)
+ __gitcomp "$__git_fetch_options"
+ return
+ ;;
+ esac
+ __git_complete_remote_or_refspec
+}
+
+_git_freeze ()
+{
+ case "$cur" in
+ -*)
+ __gitcomp "-m"
+ return
+ ;;
+ esac
+ __git_complete_file
+}
+
+
+_git_gc ()
+{
+# case "$cur" in
+# --*)
+# __gitcomp "--prune --aggressive"
+# return
+# ;;
+# esac
+ COMPREPLY=()
+}
+
+
+__git_match_ctag() {
+ awk "/^${1////\\/}/ { print \$1 }" "$2"
+}
+
+_git_gp ()
+{
+ __git_has_doubledash && return
+
+ case "$cur" in
+ --*)
+ __gitcomp "
+ --cached
+ --text --ignore-case --word-regexp --invert-match
+ --full-name --line-number
+ --extended-regexp --basic-regexp --fixed-strings
+ --perl-regexp
+ --files-with-matches --name-only
+ --files-without-match
+ --max-depth
+ --count
+ --and --or --not --all-match
+ "
+ return
+ ;;
+ esac
+
+ case "$cword,$prev" in
+ 2,*|*,-*)
+ if test -r tags; then
+ __gitcomp_nl "$(__git_match_ctag "$cur" tags)"
+ return
+ fi
+ ;;
+ esac
+
+ __gitcomp_nl "$(__git_refs)"
+}
+
+_git_grep() {
+ _git_gp
+}
+
+_git_init ()
+{
+ case "$cur" in
+ --shared=*)
+ __gitcomp "
+ false true umask group all world everybody
+ " "" "${cur##--shared=}"
+ return
+ ;;
+ --*)
+ __gitcomp "--quiet --bare --template= --shared --shared="
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
+
+_git_key ()
+{
+ case "$cur" in
+ -*)
+ __gitcomp "
+ -gen
+ "
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
+_git_ls ()
+{
+ __git_has_doubledash && return
+
+ case "$cur" in
+ --*)
+ __gitcomp "--cached --deleted --modified --others --ignored
+ --stage --directory --no-empty-directory --unmerged
+ --killed --exclude= --exclude-from=
+ --exclude-per-directory= --exclude-standard
+ --error-unmatch --with-tree= --full-name
+ --abbrev --ignored --exclude-per-directory
+ "
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
+_git_ls_files ()
+{
+ _git_ls
+}
+
+# Options that go well for log, shortlog and gitk
+__git_log_common_options="
+ --not --all
+ --branches --tags --remotes
+ --first-parent --merges --no-merges
+ --max-count=
+ --max-age= --since= --after=
+ --min-age= --until= --before=
+ --min-parents= --max-parents=
+ --no-min-parents --no-max-parents
+"
+# Options that go well for log and gitk (not shortlog)
+__git_log_gitk_options="
+ --dense --sparse --full-history
+ --simplify-merges --simplify-by-decoration
+ --left-right --notes --no-notes
+"
+# Options that go well for log and shortlog (not gitk)
+__git_log_shortlog_options="
+ --author= --committer= --grep=
+ --all-match
+"
+
+__git_log_pretty_formats="oneline short medium full fuller email raw format:"
+__git_log_date_formats="relative iso8601 rfc2822 short local default raw"
+
+_git_lg ()
+{
+ __git_has_doubledash && return
+
+ local g="$("$GIT_EXE" rev-parse --git-dir 2>/dev/null)"
+ local merge=""
+ if [ -f "$g/MERGE_HEAD" ]; then
+ merge="--merge"
+ fi
+ case "$cur" in
+ --pretty=*|--format=*)
+ __gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
+ " "" "${cur#*=}"
+ return
+ ;;
+ --date=*)
+ __gitcomp "$__git_log_date_formats" "" "${cur##--date=}"
+ return
+ ;;
+ --decorate=*)
+ __gitcomp "long short" "" "${cur##--decorate=}"
+ return
+ ;;
+ --*)
+ __gitcomp "
+ $__git_log_common_options
+ $__git_log_shortlog_options
+ $__git_log_gitk_options
+ --root --topo-order --date-order --reverse
+ --follow --full-diff
+ --abbrev-commit --abbrev=
+ --relative-date --date=
+ --pretty= --format= --oneline
+ --cherry-pick
+ --graph
+ --decorate --decorate=
+ --walk-reflogs
+ --parents --children
+ $merge
+ $__git_diff_common_options
+ --pickaxe-all --pickaxe-regex
+ "
+ return
+ ;;
+ esac
+ __git_complete_revlist
+}
+
+_git_log () {
+ _git_lg
+}
+
+__git_merge_options="
+ --no-commit --no-stat --log --no-log --squash --strategy
+ --commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit
+"
+
+_git_mg ()
+{
+ __git_complete_strategy && return
+
+ case "$cur" in
+ --*)
+ __gitcomp "$__git_merge_options"
+ return
+ esac
+ __gitcomp_nl "$(__git_refs)"
+}
+
+_git_merge ()
+{
+ _git_mg
+}
+
+_git_mt ()
+{
+ case "$cur" in
+ --tool=*)
+ __gitcomp "$__git_mergetools_common tortoisemerge" "" "${cur##--tool=}"