Compare commits

..

No commits in common. "main" and "6.2.0" have entirely different histories.
main ... 6.2.0

255 changed files with 2754 additions and 8989 deletions

View file

@ -1,30 +0,0 @@
root = true
[*]
indent_style = space
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile]
indent_style = tab
[*.patch]
trim_trailing_whitespace = false
[*.md]
trim_trailing_whitespace = false
[*.html]
trim_trailing_whitespace = false
[*.py]
indent_size = 4
[*.bats]
indent_style = tab
indent_size = 4
[tests/*.sh]
indent_style = tab
indent_size = 4

View file

@ -1,2 +0,0 @@
gool
Cant

View file

@ -1,12 +0,0 @@
<!--
Note
* Mark the PR as draft until it's ready to be reviewed.
* Please update the documentation to reflect the changes made in the PR.
* If the command is covered by tests under ./tests, please add/update tests for any changes unless you have a good reason.
* Make a new commit to resolve conversations instead of `push -f`.
* To resolve merge conflicts, merge from the `main` branch instead of rebasing over `main`.
* Please wait for the reviewer to mark a conversation as resolved.
-->

View file

@ -1,6 +0,0 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View file

@ -1,112 +1,28 @@
name: ci
on:
push:
branches: [main]
branches: [ master ]
pull_request:
branches: [main]
branches: [ master ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Check out code.
uses: actions/checkout@v7
with:
fetch-depth: 0
- name: 'Get Changed Files'
id: 'files'
run: |
CHANGED_FILES=$(git diff --name-only "${BASE_SHA:-$BEFORE_SHA}...${HEAD_SHA:-$GITHUB_REF}")
echo "::notice::Changed files: $CHANGED_FILES"
{
echo "added_modified<<EOF"
echo "$CHANGED_FILES"
echo "EOF"
} >> "$GITHUB_OUTPUT"
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
BEFORE_SHA: "${{ github.event.before }}"
- name: 'Check Generated Manuals'
run: |
failed=0
while IFS= read -r source; do
case "$source" in
man/git-*.md)
stem=${source%.md}
for generated in "$stem.1" "$stem.html"; do
if ! grep -Fqx -- "$generated" <<< "$CHANGED_FILES"; then
echo "::error file=$source::$generated must be updated with $source"
failed=1
fi
done
;;
esac
done <<< "$CHANGED_FILES"
exit "$failed"
env:
CHANGED_FILES: "${{ steps.files.outputs.added_modified }}"
- uses: 'actions/setup-go@v7'
with:
go-version: '1.20'
- name: 'Install EditorConfig Lint'
run: go install 'github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@latest'
- name: 'Check EditorConfig Lint'
run: echo "$FILES" | xargs ~/go/bin/editorconfig-checker
env:
# NOTE: use env to pass the output in order to avoid possible injection attacks
FILES: "${{ steps.files.outputs.added_modified }}"
- name: checkstyle
run: ./scripts/checkstyle.py
- name: Shellcheck
run: shellcheck --severity=error bin/* ./*.sh
typo:
runs-on: ubuntu-latest
steps:
- name: Check out code.
uses: actions/checkout@v7
- name: Install codespell
run: python3 -m pip install codespell==2.4
- name: spell check
run: |
git grep --cached -l '' . | \
grep -v -e 'History\.md' -e 'AUTHORS' -e 'man/.*\.1' -e 'man/.*\.html' | \
xargs codespell --ignore-words=.github/.ignore_words
test-bats:
name: 'Test with Bats'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
submodules: recursive
- name: Setup Bats
id: setup-bats
uses: bats-core/bats-action@4.0.0
with:
bats-version: 'v1.8.1'
- name: Test with Bats
env:
BATS_LIB_PATH: ${{ steps.setup-bats.outputs.lib-path }}
TERM: xterm
run: bats ./tests
build:
strategy:
fail-fast: false
matrix:
platform:
- ubuntu-latest
- ubuntu-18.04
- macos-latest
runs-on: ${{ matrix.platform }}
steps:
- name: Check out code.
uses: actions/checkout@v7
uses: actions/checkout@v2
- name: Linux Install
if: matrix.platform == 'ubuntu-latest'
run: sudo apt-get install -y bsdmainutils
if: matrix.platform == 'ubuntu-18.04'
run: |
sudo apt-get install -y bsdmainutils
- name: Script
run: ./check_integrity.sh
run: |
./check_integrity.sh $(find bin | cut -b 5- | xargs)
- name: Brew release
if: matrix.platform == 'macos-latest'
run: |

View file

@ -1,18 +0,0 @@
name: "Maintenance: Close Stale PRs"
on:
schedule:
- cron: "30 1 * * *"
permissions:
pull-requests: "write"
jobs:
stale:
runs-on: "ubuntu-latest"
if: github.repository_owner == 'tj'
steps:
- uses: "actions/stale@v11"
with:
close-pr-message: "This PR was closed because it has been stalled for 365 days with no activity. Feel free to make a new PR if you wish to continue"
days-before-pr-stale: 350
days-before-pr-close: 15

3
.gitignore vendored
View file

@ -1,3 +0,0 @@
.venv/
__pycache__/
coverage/

3
.gitmodules vendored
View file

@ -1,3 +0,0 @@
[submodule "vendor/bats-all"]
path = vendor/bats-all
url = https://github.com/hyperupcall/bats-all

View file

@ -1,5 +0,0 @@
[pytest]
minversion = 7.4
addopts = -ra -q
testpaths = tests
faulthandler_timeout = 5

73
AUTHORS
View file

@ -1,23 +1,24 @@
git-extras is written and maintained by various contributors:
git-extras is written and maintained by TJ Holowaychuk and
various contributors:
Development Lead
````````````````
- TJ Holowaychuk <tj@vision-media.ca>
Maintainers
```````````
- TJ Holowaychuk <tj@vision-media.ca>
- Hemanth.HM <hemanth.hm@gmail.com>
- Nimit Kalra <me@nimit.io>
- Nicolai Skogheim <nicolai.skogheim@gmail.com>
- spacewander <spacewanderlzx@gmail.com>
- Edwin Kofler <edwin@kofler.dev>
- Leroy <vanpipy@gmail.com>
Patches and Suggestions
```````````````````````
- Jonhnny Weslley
- Tobias Fendin
- LeeW
- timfeirg
- Niklas Schlimm
- nickl-
- timfeirg
- CJ
- Paul Wise
- Damien Tardy-Panis
@ -25,7 +26,6 @@ Patches and Suggestions
- Yuriy VG
- Leila Muhtasib
- Richard Fearn
- Bill Wood
- Jesús Espino
- Rémy HUBSCHER
- go2null
@ -34,20 +34,13 @@ Patches and Suggestions
- Jan Schulz
- Kenneth Reitz
- Mark Pitman
- Peter Benjamin
- Günther Grill
- Luke Childs
- Sasha Khamkov
- equt
- oikarinen
- vyas
- Don Harper
- Pierre Ayoub
- Robin Winslow
- Ross Smith II
- Yi EungJun
- grindhold
- wyattscarpenter
- Aggelos Orfanakos
- Camille Reynders
- Carlos Prado
@ -59,34 +52,29 @@ Patches and Suggestions
- Rico Sta. Cruz
- Takuma Yamaguchi
- thomas menzel
- vanpipy
- vr8ce
- Brian J Brennan
- Dominik Gedon
- Hogan Long
- Ivan Malopinsky
- John Bachir
- Jonathan "Duke" Leto
- Julio Napurí
- Justin Dugger
- Nils Winkler
- Philipp Klose
- Raphael Boidol
- Richard Russon
- Sam Bostock
- Vladimir Jimenez
- gisphm
- jacobherrington
- overengineer
- phigoro
- wooorm
- Alexis GRIMALDI
- Allan Odgaard
- Andre Cerqueira
- Austin Ziegler
- Beth Skurrie
- Brice Dutheil
- Curtis McEnroe
- Daniele Paolella
- David Rogers
- Devin Withers
- Domenico Rotiroti
@ -95,9 +83,7 @@ Patches and Suggestions
- Gert Van Gool
- Guillaume Seren
- Hozefa
- Igor Ostapenko
- Jean Jordaan
- Joshua Li
- Justin Guenther
- Kylie McClain
- Marc Harter
@ -131,7 +117,6 @@ Patches and Suggestions
- Andrew Griffiths
- Andrew Marcinkevičius
- Andrew Starr-Bochicchio
- Andrew Sullivan Cant
- Andrey Elizarov
- Angel Aguilera
- Antoine Beaupré
@ -148,10 +133,7 @@ Patches and Suggestions
- Carlos Rodríguez
- Christophe Badoit
- Ciro Nunes
- CleanMachine1
- CodeByZach
- Craig MacGregor
- Dan Goodliffe
- Dan Jackson
- Dan Kilman
- Daniel Bruder
@ -164,97 +146,69 @@ Patches and Suggestions
- Edward Betts
- Eli Schwartz
- Emil Kjelsrud
- Erik Skultety
- François M
- George Crabtree
- Gerrit-K
- Greg Allen
- Guilhem Saurel
- Guillermo Rauch
- Gunnlaugur Thor Briem
- Hasse Ramlev Hansen
- Heiko Becker
- Hugo Ruiz-Mireles
- Isaac Mungai
- J.C. Yamokoski
- Jack O. Wasey
- James Manning
- James Zhu
- Jan Krueger
- Jared Baur
- Jarod Stewart
- Jason Young
- Jens K. Mueller
- Jeremy Lin
- Jesse Sipprell
- Jianjin Fan
- Jobin Kurian
- Johannes Ewald
- John Evans
- John Hoffmann
- Jon Ander Peñalba
- Josh McKinney
- Joshua Appelman
- José María Gutiérrez @TheTechOddBug
- Katrin Leinweber
- Kevin Woo
- Konstantin Schukraft
- Kurban Mallachiev
- Leandro López
- Lone
- Luis Miguel Hernanz
- Maarten Winter
- Marco Glasbergen
- Matan Rosenberg
- Mathieu D. (MatToufoutu)
- Matt
- Matt Colyer
- Matt Headley
- Matthew Avant
- Mattias Andersson
- Michael Komitee
- Michael Matuzak
- Michele Bologna
- Montak Oleg
- Moritz Grauel
- Nate Eagleson
- Nate Fischer
- Nathan Rajlich
- Nick Campbell
- Nick Payne
- Nicolas Kosinski
- Niklas Fiekas
- Oliver Kopp
- Orestis
- Peter Bittner
- Piotr Górski
- Prayag Verma
- Przemek Kitszel
- R. Martinho Fernandes
- Raphael Fleischlin
- Rasmus Wriedt Larsen
- René
- Revisor
- Ricardo Fernández Serrata
- Riceball LEE
- Rob Kennedy
- Robin von Bülow
- Russ
- Ryan Bohn
- Sachin Gupta
- Sam Thursfield
- Sandro
- Sascha Andres
- SchleimKeim
- Sean Molenaar
- Sebastian Gniazdowski
- Sebastián Mancilla
- Simon Tate
- Stefan VanBuren
- Stephen Mathieson
- Steve Mao
- Stu Feldt
- SukkaW
- Tim Preston
- Timothy Hwang
- Tin Lai
@ -265,32 +219,21 @@ Patches and Suggestions
- TweeKane
- Valérian Galliat
- Vitaly Chikunov
- Wei Lee
- Wei Wu
- Wen Sun
- Wiktor Żurawik
- Xavier Krantz
- Xiaopei Li
- Zeeshan Ahmed
- ax1036
- creynders
- dead-horse
- eszabpt
- fengkx
- johnpyp
- jykntr
- kang
- meza
- neydroid
- nulltask
- phanium
- sgleizes
- tfendin
- tiemonl
- zentarul
- zeroDivisible
- zhiyanfoo
- Áron Hoffmann
- Étienne BERSAC
- ☃ pitr
- 单元源

View file

@ -1,22 +1,15 @@
# Contributing
## Your new git-extra command should support
Thanks for contributing! Please read this document before you make a PR.
* OSX, Linux, BSD (You may need to browse their man page)<sup>*</sup>
* Bash 3.2+ (If you aren't sure, see [the Bash changelog](https://www.tldp.org/LDP/abs/html/bash2.html))
* Git 2.1+
## Supported Platforms
<sup>*</sup>If you aren't able to test your new command on a platform,
make that clear in your PR and someone else may be able to test it on their system.
Any changes must support the following platforms:
## To submit a new command, you should
- macOS
- Linux
- OpenBSD (You may need to browse their man page)
Your change must also be compatible with the dependency constraints that we specify in [Installation](./Installation.md). If you aren't sure if a feature is compatible, check the manual or release notes. For example, the Bash changelog is [here](https://git.savannah.gnu.org/cgit/bash.git/tree/NEWS?h=devel).
If you aren't able to test your new command on a platform, make that clear in your PR; someone else may be able to test it on their system.
## Adding a New Command
Let's say you wish to add a new command. Assuming your new command is named `foo`:
Let's assume your new command is named `foo`.
1. Write a bash script under `./bin` called `git-foo`. The script should be started with `#!/usr/bin/env bash`.
2. Read `./man/Readme.md` and write documentation for `git-foo`.
@ -24,11 +17,6 @@ Let's say you wish to add a new command. Assuming your new command is named `foo
4. Update `./etc/git-extras-completion.zsh`. Just follow existing code.
5. (Optional) Update `./etc/bash_completion.sh`.
6. (Optional) Update `./etc/git-extras.fish`.
7. (Optional) Add a test under `./tests`.
8. Run `./check_integrity.sh foo` to check if all done. (You may also run `./check_integrity.sh` to check all commands.)
7. Run `./check_integrity.sh foo` to check if all done.
You are welcome to open up an issue to discuss new commands or features before opening a pull request.
## Submitting a pull request
Please follow the suggestion in `./.github/PULL_REQUEST_TEMPLATE.md`.

View file

@ -1,10 +1,8 @@
- [`git abort`](#git-abort)
- [`git alias`](#git-alias)
- [`git archive-file`](#git-archive-file)
- [`git authors`](#git-authors)
- [`git browse`](#git-browse)
- [`git browse-ci`](#git-browse-ci)
- [`git bulk`](#git-bulk)
- [`git brv`](#git-brv)
- [`git changelog`](#git-changelog)
@ -12,15 +10,12 @@
- [`git clear-soft`](#git-clear-soft)
- [`git coauthor`](#git-coauthor)
- [`git commits-since`](#git-commits-since)
- [`git continue`](#git-continue)
- [`git contrib`](#git-contrib)
- [`git count`](#git-count)
- [`git cp`](#git-cp)
- [`git create-branch`](#git-create-branch)
- [`git delete-branch`](#git-delete-branch)
- [`git delete-gone-branches`](#git-delete-gone-branches)
- [`git delete-merged-branches`](#git-delete-merged-branches)
- [`git delete-squashed-branches`](#git-delete-squashed-branches)
- [`git delete-submodule`](#git-delete-submodule)
- [`git delete-tag`](#git-delete-tag)
- [`git delta`](#git-delta)
@ -30,7 +25,6 @@
- [`git force-clone`](#git-force-clone)
- [`git fork`](#git-fork)
- [`git fresh-branch`](#git-fresh-branch)
- [`git get`](#git-get)
- [`git gh-pages`](#git-gh-pages)
- [`git graft`](#git-graft)
- [`git guilt`](#git-guilt)
@ -40,7 +34,6 @@
- [`git local-commits`](#git-local-commits)
- [`git lock`](#git-lock)
- [`git locked`](#git-locked)
- [`git magic`](#git-magic)
- [`git merge-into`](#git-merge-into)
- [`git merge-repo`](#git-merge-repo)
- [`git missing`](#git-missing)
@ -54,7 +47,6 @@
- [`git rebase-patch`](#git-rebase-patch)
- [`git release`](#git-release)
- [`git rename-branch`](#git-rename-branch)
- [`git rename-file`](#git-rename-file)
- [`git rename-tag`](#git-rename-tag)
- [`git rename-remote`](#git-rename-remote)
- [`git repl`](#git-repl)
@ -76,8 +68,6 @@
- [`git undo`](#git-undo)
- [`git unlock`](#git-unlock)
- [`git utimes`](#git-utimes)
- [`git unwip`](#git-unwip)
- [`git wip`](#git-wip)
## git extras
@ -152,20 +142,17 @@ visionmedia (18):
## git summary
Outputs a repo or path summary:
Outputs a repo summary:
```bash
$ git summary
project : git-extras
repo age : 10 months ago
branch : master
last active : 3 weeks ago
active on : 93 days
commits : 163
files : 93
uncommitted : 3
authors :
project : git-extras
repo age : 10 months ago
commits : 163
active : 60 days
files : 93
authors :
97 Tj Holowaychuk 59.5%
37 Jonhnny Weslley 22.7%
8 Kenneth Reitz 4.9%
@ -182,8 +169,8 @@ authors :
1 Guillermo Rauch 0.6%
```
This command can also take a *committish*, and will print a summary for commits in
the committish range:
This command can also take a *commitish*, and will print a summary for commits in
the commitish range:
```bash
$ git summary v42..
@ -226,20 +213,6 @@ project : git-extras
1 Daniel Schildt 0.0%
```
The `--line` option can also take a path, which will print a filtered summary for that folder or file.
The option `--output-style` tries to put as much summary information of the repo into defined styled way as possible.
This is how the `tabular` output style and `oneline` output style look like
```bash
$ git summary --output-style tabular
# Repo | Age | Last active | Active on | Commits | Uncommitted | Branch
git-extras | 13 years | 7 hours ago | 807 days | 1703 | 3 | master
$ git summary --output-style oneline
git-extras / age: 13 years / last active: 7 hours ago / active on 807 days / commits: 1703 / uncommitted: 3 / branch: master
```
## git effort
Displays "effort" statistics, currently just the number of commits per file, showing highlighting where the most activity is. The "active days" column is the total number of days which contributed modifications to this file.
@ -248,6 +221,8 @@ git-extras / age: 13 years / last active: 7 hours ago / active on 807 days / com
node (master): git effort --above 15 {src,lib}/*
```
![git effort](http://f.cl.ly/items/0b0w0S2K1d100e2T1a0D/Screen%20Shot%202012-02-08%20at%206.43.34%20PM.png)
If you wish to ignore files with commits `<=` a value you may use `--above`:
```
@ -283,20 +258,11 @@ usage: git bulk [-g] ([-a]|[-w <ws-name>]) <git command>
git bulk --listall
```
Register a workspace so that `git bulk` knows about it (it will be registered in your `.gitconfig`):
Register a workspace so that `git bulk` knows about it (notice that <ws-root-directory> must be absolute path):
```bash
$ git bulk --addworkspace personal ~/workspaces/personal
```
Notice that `<ws-root-directory>` must be an absolute path (or an environment variable pointing to an absolute path).
In the case of a **single quoted environment variable**, it will be dereferenced at `git-bulk` runtime, suitable for dynamic workspaces (*e.g.*, defined in your `.bashrc`).
As an illustration:
```bash
$ git bulk --addworkspace personal '$PERSONAL_WORKSPACE'
```
With option `--from` the URL to a single repository or a file containing multiple URLs can be added and they will be cloned directly into the workspace. Suitable for the initial setup of a multi-repo project.
```bash
@ -373,13 +339,6 @@ $ git brv
2020-01-08 master origin/master 265b03e Merge pull request #816 from spacewander/git-sed-pathspec
```
When your repo has many branches, it can be more convenient to see this list in reverse. This can be set as the default by setting the git-extras.brv.reverse git option to true.
```bash
$ git brv --reverse
2020-01-08 master origin/master 265b03e Merge pull request #816 from spacewander/git-sed-pathspec
2020-01-14 adds-git-brv fork/adds-git-brv 1ca0d76 Fixes #700: Adds git-brv
```
## git repl
@ -388,53 +347,14 @@ Git read-eval-print-loop. Lets you run `git` commands without typing 'git'.
Commands can be prefixed with an exclamation mark (!) to be interpreted as
a regular command.
Type `exit`, `quit`, or `q` to end the repl session.
Any arguments to git repl will be taken as the first command to execute in
the repl.
### CONFIGURATION
Commands entered in a repl session will be saved to a history file and be available in
future sessions, similar to a shell or programming language repl. By default,
there is one global history file, ~/.git_repl_history. You can specify that your projects
each have their own independent history file. This file will be saved in .git_repl_history
at the top level of the repo, and will need to be added to the repo or global .gitignore.
```bash
# remove the --global flag to configure only an individual project to have its own history file
git config --global git-extras.repl.use-local-history "true"
```
You can specify a default command to run when hitting enter:
```bash
git config --global git-extras.repl.on-enter-command "git status -sb"
```
You can configure which character is used at the end of the prompt: (default `>`):
```bash
git config --global git-extras.repl.prompt-character "±"
```
You can specify the prefix for the prompt, or remove it (default `git`):
```bash
git config --global git-extras.repl.prefix ""
```
You can have the name of the current git repo shown in the prompt (default `false`):
```bash
git config --global git-extras.repl.show-project-name "true"
```
Type `exit` or `quit` to end the repl session.
```bash
$ git repl
git version 2.34.1
git-extras version 7.3.0
Type 'ls' to ls files below current directory; '!command' to execute any command or just 'subcommand' to execute any git subcommand; 'quit', 'exit', 'q', ^D, or ^C to exit the git repl.
git version 2.9.2
git-extras version 3.0.0
type 'ls' to ls files below current directory,
'!command' to execute any command or just 'subcommand' to execute any git subcommand
git (master)> ls-files
History.md
@ -465,9 +385,9 @@ $ git coauthor user user@email.com
2 files changed, 145 insertions(+), 0 deletions(-)
create mode 100644 README.md
create mode 100644 CONTRIBUTING.md
$ git log -1
commit b62ceae2685e6ece071f3c3754e9b77fd0a35c88 (HEAD -> master)
Author: user person <userperson@email.com>
Date: Sat Aug 17 17:33:53 2019 -0500
@ -612,20 +532,6 @@ $ git rename-branch old-name new-name
$ git rename-branch new-name
```
## git rename-file
Rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity.
It combines the functionality of the `mv` command and `git mv`. This is particularly useful for renaming files or directories
to change only their case, which might not be detected by Git on case-insensitive filesystems.
```bash
# Rename a file
git rename-file old_filename new_filename
# Rename a directory
git rename-file old_directory new_directory
```
## git rename-tag
Rename a tag (locally and remotely).
@ -774,14 +680,14 @@ build
## git ignore-io
Generate sample gitignore file from [gitignore.io](https://www.toptal.com/developers/gitignore)
Generate sample gitignore file from [gitignore.io](https://www.gitignore.io)
Without option, `git ignore-io <type>` shows the sample gitignore of specified types on screen.
```bash
$ git ignore-io vim
# Created by https://www.toptal.com/developers/gitignore/api/vim
# Created by https://www.gitignore.io/api/vim
### Vim ###
[._]*.s[a-w][a-z]
@ -933,21 +839,6 @@ Delete local and remote tag `name`:
$ git delete-tag 0.0.1
```
## git delete-gone-branches
Deletes all local branches whose remote-tracking branch has been deleted (i.e. branches shown as `[gone]` in `git branch -vv`). Use `--dry-run` to preview what would be deleted.
```bash
$ git delete-gone-branches
Deleted branch feature-123 (was abc1234).
Deleted branch feature-456 (was def5678).
$ git delete-gone-branches --dry-run
Would delete the following branches:
feature-123
feature-456
```
## git delete-merged-branches
Deletes branches that are listed in `git branch --merged`.
@ -960,34 +851,14 @@ Deleted feature/dashboard (was 923befa).
...
```
## git delete-squashed-branches
Deletes branches that have been "squashed-merged" into a specified branch; this branch will be checked out as a side-effect. If no branch is specified, then it will default to the current checked out branch.
```bash
$ (feature-branch) git delete-squashed-branches main
Deleted branch dependabot/bundler/kramdown-2.3.1 (was 1d3fb00).
Deleted branch dependabot/bundler/rexml-3.2.5 (was a7e4052).
$ (main) git ...
```
## git fresh-branch
Create empty local branch `docs`:
Create empty local branch `name`:
```bash
$ git fresh-branch docs
```
## git get
Clone repository into a subdirectory of the configured path, `"$HOME/some-dir"`:
```bash
$ git config --global --add git-extras.get.clone-path "$HOME/some-dir"
$ git get 'https://github.com/hyperupcall/bake'
```
## git guilt
Calculate the change in blame between two revisions
@ -1042,6 +913,8 @@ $ git squash HEAD~3 "Work on a feature"
Populates the file matching `authors|contributors -i` with the authors of commits, according to the number of commits per author.
Opens the file in `$EDITOR` when set.
See the ["MAPPING AUTHORS" section](https://git-scm.com/docs/git-shortlog#_mapping_authors) of **git-shortlog**(1) to coalesce together commits by the same person.
Updating AUTHORS file:
@ -1203,14 +1076,6 @@ Internally this script uses `rsync` and not `scp` as the name suggests.
`git-rscp` - The reverse of `git-scp`. Copies specific files from the working directory of a remote repository to the current working directory.
The following options are available (must precede `<remote>`):
```bash
-v, --verbose Print what will be synced before syncing
-i, --interactive Prompt for confirmation before syncing (implies --verbose)
-n, --dry-run Show what would be synced, change nothing (implies --verbose)
```
### Examples
Copy unstaged files to remote. Useful when you want to make quick test without making any commits
@ -1371,7 +1236,7 @@ Creates a zip archive of the current git repository. The name of the archive wil
## git missing
Print out which commits are on one branch or the other but not both. Optionally, you can specify a path to limit the comparison to a specific directory or file.
Print out which commits are on one branch or the other but not both.
```bash
$ git missing master
@ -1379,12 +1244,6 @@ $ git missing master
> 97ef387 only on master
```
```bash
$ git missing master -- src/
< ed52989 only on current branch, in src/ directory
> 7988c4b only on master, in src/ directory
```
## git lock
Lock a local file `filename`:
@ -1428,8 +1287,8 @@ $ git reset-file .htaccess dc82b19
## git mr
Checks out a merge request from GitLab, or a pull request from Forgejo/Codeberg.
Usage: `git mr <ID|URL> [REMOTE]`. Default remote is `origin`.
Checks out a merge request from GitLab. Usage: `git mr <ID|URL> [REMOTE]`.
Default remote is `origin`.
``` bash
$ git mr 51
@ -1441,21 +1300,12 @@ Switched to branch 'mr/51'
With full URL, the head is fetched from a temporary remote pointing to the base URL.
``` bash
$ git mr https://gitlab.com/owner/repository/merge_requests/51
$ git mr https://gitlab.com/owner/repository/merge_requests/51
From gitlab.com:owner/repository
* [new ref] refs/merge-requests/51/head -> mr/51
Switched to branch 'mr/51'
```
A Forgejo/Codeberg pull request URL is also supported:
``` bash
$ git mr https://codeberg.org/owner/repository/pulls/51
From codeberg.org:owner/repository
* [new ref] refs/pull/51/head -> mr/51
Switched to branch 'mr/51'
```
Just like [git pr](#git-pr), `git mr` accepts a `clean` argument to trash all
`mr/` branches. Ensure current branch is not one.
@ -1638,31 +1488,16 @@ Opens the current git repository website in your default web browser.
```bash
$ git browse
$ git browse upstream
```
## git browse-ci
Opens the current git repository CI website (e.g. GitHub Actions, GitLab CI,
Bitbucket Pipelines) in your default web browser.
```bash
$ git browse-ci
$ git browse-ci upstream
```
## git utimes
Change files modification time to their last commit date. Does not touch files that are in the working tree or index.
The `--newer` flag preserves the original modification time of files that were committed from the local repo, by only touching files that are newer than their last commit date.
Change files modification time to their last commit date.
```bash
git-extras$ ls -l bin | head
total 308
-rwxr-xr-x 1 vt vt 489 Jul 28 2015 git-alias
-rwxr-xr-x 1 vt vt 489 Nov 8 13:56 git-alias
-rwxr-xr-x 1 vt vt 1043 Nov 8 13:56 git-archive-file
-rwxr-xr-x 1 vt vt 970 Nov 8 13:56 git-authors
-rwxr-xr-x 1 vt vt 267 Nov 8 13:56 git-back
@ -1671,8 +1506,8 @@ total 308
-rwxr-xr-x 1 vt vt 6282 Nov 8 13:56 git-bulk
-rwxr-xr-x 1 vt vt 18561 Nov 8 13:56 git-changelog
-rwxr-xr-x 1 vt vt 215 Nov 8 13:56 git-clear
git-extras$ git utimes --newer
git-extras$ git utimes
+ touch -d 2015-08-09T19:27:49+08:00 bin/git-alias
+ touch -d 2020-05-22T10:40:29+08:00 bin/git-archive-file
+ touch -d 2017-05-05T16:02:09+08:00 bin/git-authors
+ touch -d 2020-02-23T11:41:54+08:00 bin/git-back
@ -1682,10 +1517,9 @@ git-extras$ git utimes --newer
+ touch -d 2019-09-05T12:41:38+08:00 bin/git-changelog
+ touch -d 2016-11-19T16:41:19+00:00 bin/git-clear
[...]
git-extras$ ls -l bin | head
total 308
-rwxr-xr-x 1 vt vt 489 Jul 28 2015 git-alias
-rwxr-xr-x 1 vt vt 489 Aug 9 2015 git-alias
-rwxr-xr-x 1 vt vt 1043 May 22 05:40 git-archive-file
-rwxr-xr-x 1 vt vt 970 May 5 2017 git-authors
-rwxr-xr-x 1 vt vt 267 Feb 23 2020 git-back
@ -1695,35 +1529,3 @@ total 308
-rwxr-xr-x 1 vt vt 18561 Sep 5 2019 git-changelog
-rwxr-xr-x 1 vt vt 215 Nov 19 2016 git-clear
```
Note above, that because of the `--newer` flag, the file `git-alias` was not touched since its modified date is earlier than the commit date.
## git abort
Abort current revert, rebase, merge or cherry-pick, without the need to find exact command in history.
## git magic
Commits changes with a generated message.
## git continue
Continue current revert, rebase, merge or cherry-pick, without the need to find exact command in history.
## git wip
Create a Work In Progress(WIP) commit, which will include all changes in the
working directory. (i.e., changes to existing files, new files, removed files)
```bash
$ git wip
```
## git unwip
Undo a Work In Progress(WIP) commit and put all of those changes back into the
working directory.
```bash
$ git unwip
```

View file

@ -1,298 +1,4 @@
7.5.0 / 2026-05-09
==================
* Use standard prefix for home dir installs (#1248)
* refactor(abort): common `gitdir` (#1244)
* Fix man page usage docs (#1241)
* Fix `git-changelog` to handle whitespace in command arguments (#1232)
* chore(deps): bump bats-core/bats-action from 3.0.1 to 4.0.0 (#1230)
* add details when multiple active operations found (#1229)
* Add persistent history to `git-repl` (#1226)
* Support passing ref to `git-commits-since` (#1228)
* ability to specify command when hitting enter (#1223)
* Improve `git-repl` prompt (#1224)
* feat: `delete-branch` multiple unique branch names completions (#1221)
* chore(deps): bump actions/checkout from 5 to 6 (#1219)
* Made Git Magic use `--force-with-lease` (#1218)
* chore(deps): bump actions/stale from 9 to 10 (#1214)
* chore(deps): bump actions/setup-go from 5 to 6 (#1215)
* chore(deps): bump actions/setup-python from 5 to 6 (#1216)
* Fix minor typo in `git rename-branch` man page (#1211)
* Improvements to Bash completion (#1210)
* Fix use of `git-whatchanged` to `git-log` (#1212)
* chore(deps): bump actions/checkout from 4 to 5 (#1209)
* Bump version to 7.5.0-dev (#1207)
7.4.0 / 2025-06-19
==================
* Format comparisons, functions, and redirections to be consistent (#1201)
* add git-wip and git-unwip (#669)
* chore(deps): bump bats-core/bats-action from 3.0.0 to 3.0.1
* Mostly finish pytest to Bats conversion (#1200)
* Implement half of tests in Bats (#1187)
* Add stale bot for old PRs (#1186)
* feat(git-bulk): add new option to not follow hidden directories (#1195)
* Feat: allow git-summary showing full path of repository (#1193)
* feat(git-bulk): add new option to no follow symlinks (#1194)
* docs(git-bulk): Add zsh completion (#1190)
* fix(git-bulk): fix workspace selection when cd fails (#1197)
* fix(git-bulk): quiet find errors by default (#1196)
* fix(git-bulk): fix a bad integer expression (#1198)
* chore(deps): bump astral-sh/ruff-action from 2 to 3 (#1189)
* Fix all ShellCheck errors and add to CI (#1179)
* chore(deps): bump astral-sh/ruff-action from 1 to 2 (#1188)
* fix(ci): use poetry (#1183)
* Delete etc/test.fish (#1185)
* feat: add git-continue (#1176)
* feat: add ruff linter with ci check (#1182)
* fix(ci): missing dollar sign (#1184)
* fix(github-actions): changed files output for editorcondig-checker (#1180)
* Revert "feat: add ruff linter with ci check (#1178)" (#1181)
* feat: add ruff linter with ci check (#1178)
* Support `GITHUB_TOKEN` var for `git-fork` and `git-pull-request` (#1177)
* Bump version to 7.4.0-dev (#1175)
7.3.0 / 2024-10-20
==================
* Fix stripping trailing forward slash for git-get (#1172)
* Change git-cp to use cleaner branch approach (#1169)
* Improve warning for `git clear` (#1168)
* Enhance `git-repl` (#1160)
* Update some documentation that was out of sync (#1164)
* Use filetimes in check_integrity (#1162)
* Update git-alias.md: add brs to prevent incorrect line behavior (#1161)
* Update git-bulk.md: use correct stylization in synopsis (#1163)
* Update git-repl.md: typo: "let's" for "lets" (#1158)
* Update instructions for the OpenSUSE installation (#1157)
* Add pathspec support in `git-missing` (#1156)
* feat: add rename-file command (#1149)
* Update Commands.md (#1148)
* fix: git-summary commit count (#1147)
* tests: update dependencies (#1142)
* chore(deps): bump masesgroup/retrieve-changed-files from 2 to 3 (#1144)
* chore(deps): bump actions/setup-go from 4 to 5 (#1143)
* ci: add dependabot update for GitHub actions (#1141)
* ci: update actions (#1140)
* Bump version to 7.3.0-dev (#1139)
7.2.0 / 2024-04-21
==================
* refactor: test utils and simplify the case code (#1136)
* Add --proceed flag to git-delete-squashed-branches (#1134) (#1135)
* test(browse-ci): add unit tests (#1130)
* test(git-browse): add unit tests (#1127)
* feat: add reverse option to git-brv (#1123)
* fix(utimes): change /dev/stdin to -
* fix(utimes): Support filenames with backspaces, etc. (#1122)
* chore: add poetry to handle the tests of the git extras (#1121)
* Fix typo in ci.yml (#1120)
* Fix: harden utimes, use single quotes (#1109)
* Fix: patch git-utimes (fixes #1118) (#1119)
* add pull request manner (#1113)
* maintenance: Add my name as maintainer in AUTHORS (#1117)
* test(git-authors): add unit test (#1098)
* Add more comprensive dependencies (#1111)
* fix: git-standup find error (tj#1106) (#1110)
* Improve defaults for testing suite (#1104)
* feat: Speed up utimes (#1108)
* Overhaul CONTRIBUTING document (#1103)
* Bump version to 7.2.0-dev (#1099)
7.1.0 / 2023-10-28
==================
* git-cp: don't stop execution when merge.ff is not set (#1096)
* Allow `git cp` to create destination folder automatically (#1091)
* fix: Use `-iname` and expressions instead of `-iregex` (#1094)
* change installation source from master to main (#1092)
* test(git-archive-file): add unit test (#1084)
* ci: Use Go v1.20 for running `editorconfig-checker` (#1086)
* test(git-alias): add its unit test (#1077)
* makefile: Allow bypassing conflict check (#1080)
* fix: Restore zsh completions to working completion (#1079)
* fix: add missing quote in git-extras-completion.zsh (#1078)
* feat: Implement completion for `git coauthor` (#1074)
* fix: Move improvements via ShellCheck (#1075)
* feat(auto-test): CI with pytest (#1066)
* git-feature: add configurable branch separator (#1072)
* git-psykorebase: determine branch names with bash pattern substitution (#1073)
* git-cp: continue to merge when merge.ff is only (#1070)
* git archive-file: change base ARCHIVE_NAME (#1071)
* readme: Add secondary location of screencast (#1065)
* fix: Improve Bash hygiene (#1056)
* feat: Implement `git-get` command (#1045)
* Corrected grammar in bin/git-cp (#1061)
* Improve `git-ignore` command (#1047)
* I have made two improvements to the git-bulk: (#1054)
* Type properly `__gitex_command_successful` calls and capitalizate github to GitHub (#1049)
* Add typo checker
* Fix comment typo in git-authors (#1050)
* tweak: Fix typos (#1046)
* Makefile: init SYSCONFDIR before using it (#1044)
* Makefile: tune MANPREFIX configuration for FreeBSD (#1043)
* Makefile: set bash COMPL_DIR to FreeBSD expected defaults (#1042)
* Bump version to 7.1.0-dev (#1041)
7.0.0 / 2023-04-20
==================
* git-delete-tag: should not be quoted
* Add the current branch git summary (#1034)
* chore: Improve Bash variously (#1032)
* Change the oneline option to a tebular version in the git summary (#1031)
* chore: Remove `X`-style equality comparisons (#1028)
* chore: Various Bash improvements (#1029)
* fix: No longer pollute env with `GREP_OPTIONS`
* tweak editor config (#1027)
* revert the completion dir change on MacOS (#1026)
* Update gitignore.io urls to Toptal urls (#1025)
* Add EditorConfig file (#1022)
* Make the bulk output slimmer (#1020)
* chore: Fix more Bash inconsistencies (#1021)
* Repo status overview (#1017)
* Replace egrep with grep -E (#1019)
* chore: More Bash improvements and removing deprecations (#1016)
* chore: Improve quoting and builtin usage (#1015)
* Add summary fields (#1013)
* Fix quiet mode of the bulk command (#1014)
* git-summary: remove stray \ in grep call (#1010)
* Allow to run git-extras within git-bulk (#1008)
* Make git-summary accept multiple paths for the --lines argument (#1005)
* Makefile: ensure bash is used instead of /bin/sh (#1004)
* fix base branch in the pull-request command (#1003)
* Update docs for git abort change (#1000)
* Bump version to 6.6.0-dev (#997)
6.5.0 / 2022-10-06
==================
* git root: show '.' when using with -r in the root dir (#995)
* git standup: work as expected when no configured (#996)
* rephrase question depending on switch (#984)
* Include revert conflicts in git abort (#992)
* fix(git-effort):fork: retry: Resource temporarily unavailable #979 (#990)
* git-sync --force will sync without interaction (#989)
* fix(git-cp): keep the history of the files
* git-bulk: previous refactor redirected $PWD to stderr by mistake
* Fix lazy loading bash_completion from XDG_DATA_DIRS
* Minor changes to man/git-standup.md
* Replaced -g and -A with -F gpg|authordate
* fix(bin/git-browse): fix commit hash
* fix(bin/git-browse): fix bitbucket url
* feat: open website at file & line number or range
* #970 standup added -A flag for author date
* update docs due to formatting error in git-utimes man page
* update per shellcheck advice
* update git-utimes.{1,html} to add --newer flag
* Don't read git-extras.standup.implicit-week twice in git standup
* quote mod_s and git_s integer vars
* updates per request of spacewander
* Update Commands.md
* allow modification date updates for symbolic links
* add --newer flag and ignore files in the working tree or index
* Documented config git-extras.standup.implicit-week
* Minor change to git standup -w documentation
* Improved check if -w or -d was given to git standup
* Renamed config git-extras.standup.implicit-week from git-extras.standup-implicit-week
* Documented weekend behaviour of git standup -w
* docs(instllation): replace `git.io`
* Bump version to 6.5.0-dev
* Added config git-extras.standup-implicit-week for git standup
* Document git standup -w option
6.4.0 / 2022-04-22
==================
* Merge pull request #964 from spacewander/bro
* git-browse/browse-ci: use powershell.exe only when it is available
* Merge pull request #944 from SimonTate/feature/sem-ver-prefix
* Merge pull request #957 from jackwasey/quiet-or-stderr
* git-release: Add prefix to semver
* Merge pull request #959 from pbnj/feat/git-browse-ci
* fix: fix stderr & stdout redirect
* Merge pull request #962 from spacewander/gicc
* git-ignore-io: make sure .gi_list is created before access
* git-ignore: the directory of target file may not exist
* fix(git-browse-ci): set pipefail
* docs: fix docs
* chore: update docs & completions
* feat: implement git-browse-ci
* quiet option, errors to stderr
* Merge pull request #956 from tfendin/xargs-conflicting-args
* Removed xargs from git-effort
* Merge pull request #955 from katrinleinweber/summary-highlight-path-opt
* Highlight path option more
* Merge pull request #951 from tfendin/local-commits-all-remotes
* Updated manual for git local-commits, must track a branch
* Merge pull request #946 from tfendin/default_branch_logic
* Made local-commits work with all remotes
* Updated Readme.md after review
* Merge pull request #949 from tfendin/git-ignore-ensure-newline
* Added section about main branch to the Readme file
* Merge pull request #947 from tfendin/git-unlock-synopsis-fix
* Merge pull request #948 from tfendin/git-ignore-core-excludesFile
* Clarified comment of when newline should be added
* Updated git-extras manual after review.
* git-ignore: ensure new patterns comes after a newline
* Fixed bug in git-ignore which ignored config core.excludeFiles
* Spell corr in git-unlock synopsis
* Consider init.defaultBranch in git_extra_default_branch, changed default branch to main.
* Merge pull request #885 from spacewander/add_pkg
* doc: add packaging status
* Merge pull request #940 from overengineer/feature/magic
* Ignored error when git restore --staged fails when there is no commit
* Merge branch 'master' into merge/magic
* Added git-magic command
* Bump version to 6.4.0-dev
6.3.0 / 2021-10-02
==================
* Merge pull request #942 from spacewander/ffgd
* git-delete-squashed-branches: fail fast if can't checkout
* Merge pull request #939 from SimonTate/feature/force-clear
* git-clear: add force option
* Merge pull request #936 from tfendin/multiline_synopsis_fix
* Merge pull request #937 from tfendin/dedup_email_case_insensitive
* Merge pull request #934 from tfendin/no-merge-summary
* Adopted git --dedup-by-email to the project coding style
* summary --dedup-by-email now compares email adresses case insensitive.
* Updated lines under Synopsis in the manuals so they are commonly formatted
* Add incompability check for git summary --line --no-merges, split synopsis in its manual.
* Merge pull request #935 from ax1036/git-un-lock
* fix git (un)lock with spaced filenames
* Updated completion for git summary
* Updated documentation for git-summary --no-merges
* Added option --no-merges to git summary
* Merge pull request #932 from spacewander/git-su
* git-summary: support filtering `--line` with path
* Merge pull request #865 from pkitszel/pkitszel-git-abort
* Add git-abort
* Merge pull request #928 from duckunix/master
* Update point to github docs for forks from API
* update working
* git-fork | Update man/md/html pages to talk about need of the github personal access token
* Updated documentation (AUTHORS)
* bin/git-fork | updating for feedback from PR #928
* git-fork | update to match REST-API auth standards as of 2021-06
* Merge pull request #926 from nicokosi/patch-1
* Update install doc: Homebrew is not just for macOS
* Merge pull request #924 from allejo/feature/delete-squashed-branches
* delete-squashed-branches: Make side-effect clear in docs
* delete-squashed-branches: Make branch checkout side effect clear
* Add delete-squashed-branches command
* Merge pull request #923 from CleanMachine1/patch-1
* Picture is broken
* Merge pull request #920 from matan129/patch-1
* Ignore checked-out branches on different worktrees
* Merge pull request #917 from heirecka/remove-git-line-summary-man-page
* Bump version to 6.3.0-dev
* doc: Remove man page for git-line-summary
6.2.0 / 2021-03-26
==================

View file

@ -1,31 +1,19 @@
# Installation
# Installing git-extras
## Dependencies
Some commands require extra dependencies which are unavailable in some platforms.
You may need to install them manually. They are:
You may need to install them manually.
* bash 4.0+
* Git 2.17+
* `column`
* `awk`
* `find`
* `tput`
* cURL (only required for `git-fork`, `git-ignore-io`, `git-pull-request`)
* `ps` (only required for `git-changelog`)
* `rsync` (only required for `git-rscp`, `git-scp`)
* `xargs` (only required for `git-delete-merged-branches`, `git-force-clone`, `git-sed`, `git-scp`)
Those dependencies are listed below:
If `bash --version` shows a lower version, you need to update it.
For example, the default bash in Mac is usually too old and you may need to update it via `brew install bash`.
* column
## Installing with a package manager
Note that only the Homebrew package is maintained by the git-extras developers directly.
Other packages are maintained by the distribution's packagers or third-party volunteers.
[![Packaging status](https://repology.org/badge/vertical-allrepos/git-extras.svg)](https://repology.org/project/git-extras/versions)
### Debian
```bash
@ -41,10 +29,9 @@ $ sudo dnf install git-extras
### openSUSE
Substitute your openSUSE version in the command below (in this case we are considering openSUSE Leap 15.6):
Substitute your openSUSE version in the command below (in this case we are considering openSUSE Leap 15.2):
```bash
$ sudo zypper ar https://download.opensuse.org/repositories/devel:/tools:/scm/15.6/devel:tools:scm.repo
$ sudo zypper ar https://download.opensuse.org/repositories/devel:/tools:/scm/openSUSE_Leap_15.2/devel:tools:scm.repo
```
and install it:
@ -75,7 +62,8 @@ $ nix-env -i git-extras
[Abdullah](https://github.com/AWAN) has written a [Pkgfile](https://abdullah.today/ports/git-extras/Pkgfile) for his beloved [distro](https://crux.nu).
### Homebrew
### macOS with Homebrew
```bash
$ brew install git-extras
@ -83,6 +71,7 @@ $ brew install git-extras
Installing from Homebrew will not give you the option omit certain `git-extras` if they conflict with existing git aliases. To have this option, build from source.
### Arch Linux
* [git-extras](https://aur.archlinux.org/packages/git-extras/)
@ -92,7 +81,6 @@ Installing from Homebrew will not give you the option omit certain `git-extras`
First, please install `Git for Windows 2.x` from 'https://github.com/git-for-windows/git/releases'.
Second, clone the `git-extras` repo into any folder you like.
```bash
git clone https://github.com/tj/git-extras.git
# checkout the latest tag (optional)
@ -144,7 +132,7 @@ alternate location, specify a `PREFIX` when calling `make`.
```bash
# Non-root users can install under their home directory
make install PREFIX=$HOME/.local
make install PREFIX=$HOME/software
# For third-party software kept under /opt
make install PREFIX=/opt
@ -154,7 +142,7 @@ If you want to relocate the bulk of the installation but still have configuratio
files installed to the system `/etc` dir or other alternate location, you can
specify `SYSCONFDIR` in addition to `PREFIX`.
```sh
```
$ sudo make install PREFIX=/usr/local SYSCONFDIR=/etc
```
@ -165,13 +153,12 @@ See the Makefile for details on advanced configuration options.
One-liner:
```bash
curl -sSL https://raw.githubusercontent.com/tj/git-extras/main/install.sh | sudo bash /dev/stdin
curl -sSL https://git.io/git-extras-setup | sudo bash /dev/stdin
```
## Installing as Zsh plugin
[ZInit](https://github.com/zdharma/zinit) can install git-extras by using:
```zsh
zinit ice as"program" pick"$ZPFX/bin/git-*" src"etc/git-extras-completion.zsh" make"PREFIX=$ZPFX"
zinit light tj/git-extras

View file

@ -1,25 +1,14 @@
PREFIX ?= /usr/local
BINPREFIX ?= "$(PREFIX)/bin"
SYSCONFDIR ?= $(PREFIX)/etc
SHELL := bash
OS = $(shell uname)
ifeq ($(OS), FreeBSD)
MANPREFIX ?= "$(PREFIX)/man/man1"
ifeq ($(MANPREFIX), /usr/local)
MANPREFIX = "/usr/local/man/man1"
endif
else
MANPREFIX ?= "$(PREFIX)/share/man/man1"
endif
ifeq ($(OS), Darwin)
COMPL_DIR ?= "$(DESTDIR)$(SYSCONFDIR)/bash_completion.d"
else ifeq ($(OS), FreeBSD)
COMPL_DIR ?= "$(DESTDIR)$(SYSCONFDIR)/bash_completion.d"
else
COMPL_DIR ?= "$(DESTDIR)$(SYSCONFDIR)/bash-completion/completions"
endif
SYSCONFDIR ?= $(PREFIX)/etc
BINS = $(wildcard bin/git-*)
MANS = $(wildcard man/git-*.md)
MAN_BINS = $(filter-out man/git-extras.md, $(MANS))
@ -45,24 +34,22 @@ install: check
@if [ "$(INSTALL_VIA)" = brew ]; then \
git apply brew-release.patch || { echo "Can't apply brew release patch"; exit 1; } \
fi
mkdir -p $(DESTDIR)$(MANPREFIX)
mkdir -p $(DESTDIR)$(BINPREFIX)
@echo '... installing bins to '$(DESTDIR)$(BINPREFIX)
@echo '... installing man pages to '$(DESTDIR)$(MANPREFIX)
@mkdir -p $(DESTDIR)$(MANPREFIX)
@mkdir -p $(DESTDIR)$(BINPREFIX)
@echo "... installing bins to $(DESTDIR)$(BINPREFIX)"
@echo "... installing man pages to $(DESTDIR)$(MANPREFIX)"
$(eval TEMPFILE := $(shell mktemp -q $${TMPDIR:-/tmp}/git-extras.XXXXXX 2>/dev/null || mktemp -q))
@# chmod from rw-------(default) to rwxrwxr-x, so that users can exec the scripts
@chmod 775 $(TEMPFILE)
$(eval EXISTED_ALIASES := $(shell \
git config --get-regexp 'alias\..*' | awk '{print "git-" substr($$1, 7)}'))
git config --get-regexp 'alias.*' | awk '{print "git-" substr($$1, 7)}'))
@$(foreach COMMAND, $(COMMANDS), \
should_install='yes'; \
if [ ! -z "$(filter $(COMMAND), $(EXISTED_ALIASES))" ] && [ "$$SKIP_CONFLICT_CHECK" != yes ]; then \
read -p "$(COMMAND) conflicts with an alias, still install it? [y/n]: " answer; \
if [ "$$answer" = 'n' ] || [ "$$answer" = 'N' ]; then \
should_install="no"; \
fi; \
disable=''; \
if test ! -z "$(filter $(COMMAND), $(EXISTED_ALIASES))"; then \
read -p "$(COMMAND) conflicts with an alias, still install it and disable the alias? [y/n]" answer; \
test "$$answer" = 'n' -o "$$answer" = 'N' && disable="true"; \
fi; \
if [ "$$should_install" = 'yes' ]; then \
if test -z "$$disable"; then \
echo "... installing $(COMMAND)"; \
head -1 bin/$(COMMAND) > $(TEMPFILE); \
cat $(LIB) >> $(TEMPFILE); \
@ -82,8 +69,8 @@ install: check
cp -f man/git-*.1 $(DESTDIR)$(MANPREFIX); \
echo "cp -f man/git-*.1 $(DESTDIR)$(MANPREFIX)"; \
fi
@mkdir -p $(COMPL_DIR)
cp -f etc/bash_completion.sh $(COMPL_DIR)/git-extras
@mkdir -p $(DESTDIR)$(SYSCONFDIR)/bash_completion.d
cp -f etc/bash_completion.sh $(DESTDIR)$(SYSCONFDIR)/bash_completion.d/git-extras
@echo ""
@echo "If you are a zsh user, you may want to 'source $(CODE_DIR)etc/git-extras-completion.zsh'" \
"and put this line into ~/.zshrc to enable zsh completion"
@ -132,7 +119,7 @@ uninstall:
echo "... uninstalling $(DESTDIR)$(MANPREFIX)/$(notdir $(MAN))"; \
rm -f $(DESTDIR)$(MANPREFIX)/$(notdir $(MAN)); \
)
rm -f $(COMPL_DIR)/git-extras
rm -f $(DESTDIR)$(SYSCONFDIR)/bash_completion.d/git-extras
clean: docclean
@ -140,7 +127,4 @@ docclean:
rm -f man/*.1
rm -f man/*.html
test:
bats ./tests
.PHONY: default docs check install uninstall clean docclean test
.PHONY: default docs clean docclean check install uninstall

View file

@ -6,15 +6,15 @@ Little git extras.
Just getting started? Check out these screencasts:
* [introduction](https://vimeo.com/45506445) ([archive.org link](https://web.archive.org/web/20230219181235id_/vod-progressive.akamaized.net/exp=1676834145~acl=%2Fvimeo-prod-skyfire-std-us%2F01%2F4101%2F1%2F45506445%2F107111328.mp4~hmac=065b68f23c4b6a222463097b36d1c346995a9559baa9b819972da95550018471/vimeo-prod-skyfire-std-us/01/4101/1/45506445/107111328.mp4)) -- covers `git-ignore`, `git-setup`, `git-changelog`, `git-release`, `git-effort` and more
* [introduction](https://vimeo.com/45506445) -- covering git-ignore, git-setup, git-changelog, git-release, git-effort and more
## Installation
See the [Installation](Installation.md) page.
See [Installation](Installation.md) page.
## Commands
Go to the [Commands](Commands.md) page for basic usage and examples.
Go to [Commands](Commands.md) page for basic usage and examples.
__GIT utilities__ -- repo summary, repl, changelog population, author commit percentages and more
@ -23,12 +23,3 @@ __GIT utilities__ -- repo summary, repl, changelog population, author commit per
Interested in contributing? Awesome!
Please read [Contributing](CONTRIBUTING.md) before you make a PR, thanks!
## The change of the default branch
As of Git Extras 6.4 the assumed default branch name changed from `master` to `main`.
This affects the Git Extras commands `git archive-file`, `git delete-merged-branches`, `git delta`, `git pull-request`, `git show-merged-branches`, `git show-unmerged-branches`, and `git squash`.
To change the default branch name to `master`: change either the configuration `git-extras.default-branch` or `init.defaultBranch` to `master`; the former takes precedence.
For example, `git config git-extras.default-branch master`.

View file

@ -1,45 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# git rev-parse emits an error if not in a git repo so only need to bail out
gitdir="$(git rev-parse --git-dir)" || exit
discover_op() {
local op
for op in cherry_pick merge rebase revert ; do
if [ -f "${gitdir}/${op^^}_HEAD" ]; then
echo "${op/_/-}"
fi
done
}
validate_op() {
local op="$1"
if [ -z "$op" ]; then
echo "No active operation found" >&2
exit 1
fi
if [[ "$(echo "$op" | wc -l)" -gt 1 ]]; then
echo "Multiple active operations found:" >&2
for o in $op; do
echo " - $o: HEAD: $(cat "${gitdir}/${o}_HEAD")" >&2
done
exit 1
fi
}
discover_action() {
local action=${1/git-/}
if [ "$action" != "abort" ] && [ "$action" != "continue" ]; then
echo "Invalid action: $1" >&2
exit 1
fi
echo "$action"
}
action=$(discover_action "$(basename "$0")")
op=$(discover_op)
validate_op "$op"
git "$op" "--$action"

View file

@ -1,45 +1,16 @@
#!/usr/bin/env bash
options=""
usage() {
cat <<HERE
usage: git alias [options] # list all aliases
or: git alias [options] <search-pattern> # show aliases matching pattern
or: git alias [options] <alias-name> <command> # alias a command
options:
--global Show or create alias in the system config
--local Show or create alias in the repository config
usage: git alias # list all aliases
or: git alias <search-pattern> # show aliases matching pattern
or: git alias <alias-name> <command> # alias a command
HERE
}
if [[ "$1" == "--local" || "$1" == "--global" ]]; then
options=$1
shift
fi
case $# in
0)
if [[ -z "$options" ]]; then
git config --get-regexp 'alias.*' | sed 's/^alias\.//' | sed 's/[ ]/ = /' | sort
else
git config "$options" --get-regexp 'alias.*' | sed 's/^alias\.//' | sed 's/[ ]/ = /' | sort
fi
;;
1)
if [[ -z "$options" ]]; then
git config --get-regexp 'alias.*' | sed 's/^alias\.//' | sed 's/[ ]/ = /' | sort | grep -e "$1"
else
git config "$options" --get-regexp 'alias.*' | sed 's/^alias\.//' | sed 's/[ ]/ = /' | sort | grep -e "$1"
fi
;;
2)
if [[ -z "$options" ]]; then
git config alias."$1" "$2"
else
git config "$options" alias."$1" "$2"
fi
;;
0) git config --get-regexp 'alias.*' | sed 's/^alias\.//' | sed 's/[ ]/ = /' | sort ;;
1) git alias | grep -e "$1" ;;
2) git config --global alias."$1" "$2" ;;
*) >&2 echo "error: too many arguments." && usage && exit 1 ;;
esac

View file

@ -1,23 +1,23 @@
#!/usr/bin/env bash
# extract current branch name
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null)
# get name of the most top folder of current directory, used for the
# output filename
ARCHIVE_NAME=$(basename "$(git rev-parse --show-toplevel)")
ARCHIVE_NAME=$(basename $(pwd))
if [[ $BRANCH = tags* ]]; then
BRANCH=$(git describe)
echo Building for tag "\"$BRANCH\""
echo Building for tag \"$BRANCH\"
FILENAME=$ARCHIVE_NAME.$BRANCH.zip
else
echo Building archive on branch "\"$BRANCH\""
echo Building archive on branch \"$BRANCH\"
# get a version string, so archives will not be overwritten when creating
# many of them
VERSION=$(git describe --always --long)
# if not on master append branch name into the filename
if [ "$BRANCH" = "$(git_extra_default_branch)" ]; then
if [ "$BRANCH" = $(git_extra_default_branch) ]; then
FILENAME=$ARCHIVE_NAME.$VERSION.zip
else
FILENAME=$ARCHIVE_NAME.$VERSION.$BRANCH.zip
@ -28,10 +28,10 @@ fi
FILENAME=${FILENAME//\//-}
FILENAME=${FILENAME//\\/-}
# combine path and filename
OUTPUT=$PWD/$FILENAME
OUTPUT=$(pwd)/$FILENAME
# building archive
git archive --format zip --output "$OUTPUT" "$BRANCH"
git archive --format zip --output $OUTPUT $BRANCH
# also display size of the resulting file
echo Saved to \""$FILENAME"\" \("$(du -h "$OUTPUT" | cut -f1)"\)
echo Saved to \"$FILENAME\" \(`du -h $OUTPUT | cut -f1`\)

View file

@ -3,6 +3,7 @@
LIST=false
NO_EMAIL=false
FILE=""
EDITOR=$(git var GIT_EDITOR)
while [[ $# -gt 0 ]]; do
case $1 in
@ -21,9 +22,9 @@ done
if ! $LIST; then
FILE=$1
if [ -z "$FILE" ]; then
FILE=$(find . -mindepth 1 -maxdepth 1 \( -iname '*authors*' -o -iname '*contributors*' \) | head -n1)
if [ -z "$FILE" ]; then
if test "$FILE" = ""; then
FILE=$(ls | egrep 'authors|contributors' -i|head -n1)
if test "$FILE" = ""; then
FILE='AUTHORS'
fi
fi
@ -35,11 +36,11 @@ fi
authors() {
if $NO_EMAIL; then
# email will be used to uniq authors.
git shortlog HEAD -sne | awk '{$1=""; sub(" ", ""); print}' | awk -F'<' '!x[$1]++' | awk -F'<' '!x[$2]++' \
# eamil will be used to uniq authors.
git shortlog -sne | awk '{$1=""; sub(" ", ""); print}' | awk -F'<' '!x[$1]++' | awk -F'<' '!x[$2]++' \
| awk -F'<' '{gsub(/ +$/, "", $1); print $1}'
else
git shortlog HEAD -sne | awk '{$1=""; sub(" ", ""); print}' | awk -F'<' '!x[$1]++' | awk -F'<' '!x[$2]++'
git shortlog -sne | awk '{$1=""; sub(" ", ""); print}' | awk -F'<' '!x[$1]++' | awk -F'<' '!x[$2]++'
fi
}
@ -50,5 +51,6 @@ authors() {
if $LIST; then
authors
else
authors >> "$FILE"
authors >> $FILE
test -n "$EDITOR" && $EDITOR $FILE
fi

View file

@ -1,92 +1,54 @@
#!/usr/bin/env bash
remote=${1:-""}
branch=""
filename=${2:-""}
line1=${3:-""}
line2=${4:-""}
# get remote name
if [[ $remote == "" ]]; then
branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
if [[ $1 == "" ]]
then
branch=$(git rev-parse --abbrev-ref HEAD 2&> /dev/null)
remote=$(git config branch."${branch}".remote || echo "origin")
else
remote=$1
fi
if [[ $remote == "" ]]; then
if [[ $remote == "" ]]
then
echo "Remote not found"
exit 1
fi
remote_url=$(git remote get-url "$remote") || exit $?
remote_url=$(git remote get-url $remote)
if [[ $remote_url = git@* ]]; then
url=$(echo "$remote_url" | sed -E -e 's/:/\//' -e 's/\.git$//' -e 's/.*@(.*)/http:\/\/\1/')
elif [[ $remote_url = http* ]]; then
if [[ $? -ne 0 ]]
then
exit $?
fi
if [[ $remote_url = git@* ]]
then
url=$(echo $remote_url | sed -E -e 's/:/\//' -e 's/\.git$//' -e 's/.*@(.*)/http:\/\/\1/')
elif [[ $remote_url = http* ]]
then
url=${remote_url%.git}
fi
# construct urls
commit_hash=$(git rev-parse HEAD 2>/dev/null)
commit_or_branch=${commit_hash:-${branch}}
if [[ $remote_url =~ gitlab ]]; then
# construct gitlab urls
# https://gitlab.com/<user_or_group>/<repo>/-/blob/<commit_or_branch>/<filename>#L<line1>-<line2>
if [[ -n ${filename} ]]; then
url="${url}/-/blob/${commit_or_branch}/${filename}"
if [[ -n "${line1}" ]]; then
url="${url}#L${line1}"
if [[ -n "${line2}" ]]; then
url="${url}-${line2}"
fi
fi
fi
elif [[ $remote_url =~ github ]]; then
# construct github urls
# https://github.com/<user_or_org>/<repo>/blob/<commit_or_branch>/<filename>#L<line1>-L<line2>
if [[ -n "${filename}" ]]; then
url="${url}/blob/${commit_or_branch}/${filename}"
if [[ -n "${line1}" ]]; then
url="${url}#L${line1}"
if [[ -n "${line2}" ]]; then
url="${url}-L${line2}"
fi
fi
fi
elif [[ $remote_url =~ bitbucket ]]; then
# construct bitbucket urls
# https://bitbucket.org/<user_or_org>/<repo>/src/<commit_or_branch>/<filename>#lines-<line1>:<line2>
if [[ -n ${filename} ]]; then
url=${url}/src/${commit_or_branch}/${filename}
if [[ -n "${line1}" ]]; then
url="${url}#lines-${line1}"
if [[ -n "${line2}" ]]; then
url="${url}:${line2}"
fi
fi
fi
fi
# open url
case "$OSTYPE" in
darwin*)
# MacOS
open "$url"
;;
msys)
# Git-Bash on Windows
start "$url"
;;
linux*)
# Handle WSL on Windows
if uname -a | grep -i -q Microsoft && command -v powershell.exe; then
powershell.exe -NoProfile start "$url"
else
xdg-open "$url"
fi
;;
*)
# fall back to xdg-open for BSDs, etc.
xdg-open "$url"
;;
darwin*)
# MacOS
open $url
;;
msys)
# Git-Bash on Windows
start $url
;;
linux*)
# Handle WSL on Windows
if uname -a | grep -i -q Microsoft
then
powershell.exe -NoProfile start $url
else
xdg-open $url
fi
;;
*)
# fall back to xdg-open for BSDs, etc.
xdg-open $url
;;
esac

View file

@ -1,60 +0,0 @@
#!/usr/bin/env bash
set -e -o pipefail
if [[ $1 == "" ]]
then
branch=$(git rev-parse --abbrev-ref HEAD &> /dev/null)
remote=$(git config branch."${branch}".remote || echo "origin")
else
remote=$1
fi
if [[ -z $remote ]]
then
echo "Remote not found"
exit 1
fi
remote_url=$(git remote get-url "${remote}") || exit $?
if [[ $remote_url = git@* ]]
then
url=$(echo "${remote_url}" | sed -E -e 's/:/\//' -e 's/\.git$//' -e 's/.*@(.*)/http:\/\/\1/')
elif [[ $remote_url = http* ]]
then
url=${remote_url%.git}
fi
if [[ $url =~ github ]]
then
ci_url=${url}/actions
elif [[ $url =~ gitlab ]]
then
ci_url=${url}/-/pipelines
elif [[ $url =~ bitbucket ]]
then
ci_url=${url}/addon/pipelines/home
fi
case "$OSTYPE" in
darwin*)
# MacOS
open "${ci_url}"
;;
msys)
# Git-Bash on Windows
start "${ci_url}"
;;
linux*)
# Handle WSL on Windows
if uname -a | grep -i -q Microsoft && command -v powershell.exe
then
powershell.exe -NoProfile start "${ci_url}"
else
xdg-open "${ci_url}"
fi
;;
*)
# fall back to xdg-open for BSDs, etc.
xdg-open "${ci_url}"
;;
esac

View file

@ -7,20 +7,6 @@ if ! (( BASH_VERSINFO[0] > 4 ||
exit 1
fi
# allow the user to set a default reverse option in an environment variable
reverse=$(git config --get git-extras.brv.reverse || echo false)
while [[ $# -gt 0 ]]; do
case $1 in
-r | --reverse)
reverse=true
shift
;;
*)
break
;;
esac
done
if [[ -t 1 ]]; then
shopt -s checkwinsize
COLUMNS=$(tput cols)
@ -50,14 +36,9 @@ for b in "${!upstream[@]}"; do
done
mapfile -t ordered < <(
# the reverse option of git-brv causes the sort to be sorted normally rather than in reverse
reverse_opt=""
if [[ $reverse = false ]]; then
reverse_opt="-r"
fi
for b in "${!date[@]}"; do
printf '%d\t%s\n' "${date[$b]}" "$b"
done | sort -n $reverse_opt | cut -f2-
done | sort -rn | cut -f2-
)
current=$(git symbolic-ref -q --short HEAD)
@ -78,4 +59,4 @@ for b in "${ordered[@]}"; do
"$color_branch_upstream" "-$uwidth" "${upstream[$b]}" "$reset" \
"$color_diff_commit" "-$hwidth" "${hash[$b]}" "$reset" \
"$msg"
done
done

View file

@ -8,15 +8,12 @@ bldred=${txtbld}$(tput setaf 1)
guardedmode=false
singlemode=false
allwsmode=false
quiet=false
no_follow_symlinks=false
no_follow_hidden=false
#
# print usage message
#
usage() {
echo 1>&2 "usage: git bulk [--no-follow-symlinks] [--no-follow-hidden] [-q|--quiet] [-g] ([-a]|[-w <ws-name>]) <git command>"
echo 1>&2 "usage: git bulk [-g] ([-a]|[-w <ws-name>]) <git command>"
echo 1>&2 " git bulk --addworkspace <ws-name> <ws-root-directory> (--from <URL or file>)"
echo 1>&2 " git bulk --removeworkspace <ws-name>"
echo 1>&2 " git bulk --addcurrent <ws-name>"
@ -24,33 +21,22 @@ usage() {
echo 1>&2 " git bulk --listall"
}
cdfail() {
echo 1>&2 "failed to change directory: $1"
exit 1
}
# add another workspace to global git config
addworkspace() {
git config --global bulkworkspaces."$wsname" "$wsdir";
if [ -n "$source" ]; then
if [ ! -d "$wsdir" ]; then echo 1>&2 "Path of workspace doesn't exist, make it first."; exit 1; fi
function addworkspace {
git config --global bulkworkspaces."$wsname" "$wsdir";
if [ ! -z "$source" ]; then
if [ ! -d "$wsdir" ]; then echo "Path of workspace doesn't exist, make it first."; exit 1; fi
regex='http(s)?://|ssh://|(git@)?.*:.*/.*'
if [[ "$source" =~ $regex ]]; then
pushd "$wsdir" > /dev/null || cdfail "$wsdir"
pushd "$wsdir" > /dev/null
git clone "$source"
popd > /dev/null || cdfail "$OLDPWD"
popd > /dev/null
else
source=$(realpath "$source" 2>/dev/null)
if [ -f "$source" ]; then
pushd "$wsdir" > /dev/null || cdfail "$wsdir"
while IFS= read -r line; do
if [ -n "$line" ]; then
# the git clone command to take the complete line in the repository.txt as separate argument. This facilitated the cloning of the repository with a custom folder name.
# shellcheck disable=SC2086
git clone $line;
fi
done < "$source"
popd > /dev/null || cdfail "$OLDPWD"
pushd "$wsdir" > /dev/null
while read -r line; do git clone "$line"; done < "$source";
popd > /dev/null
else
echo 1>&2 "format of URL or file unknown"
fi
@ -59,125 +45,101 @@ addworkspace() {
}
# add current directory
addcurrent() { git config --global bulkworkspaces."$wsname" "$PWD"; }
function addcurrent { git config --global bulkworkspaces."$wsname" "$PWD"; }
# remove workspace from global git config
removeworkspace() { checkWSName && git config --global --unset bulkworkspaces."$wsname"; }
function removeworkspace { checkWSName && git config --global --unset bulkworkspaces."$wsname"; }
# remove workspace from global git config
purge() { git config --global --remove-section bulkworkspaces; }
function purge { git config --global --remove-section bulkworkspaces; }
# list all current workspace locations defined
listall() { git config --global --get-regexp bulkworkspaces; }
function listall { git config --global --get-regexp bulkworkspaces; }
# guarded execution of a git command in one specific repository
guardedExecution () {
if [ "${quiet?}" != "true" ] || $guardedmode; then
echo 1>&2 "${bldred}->${reset} executing ${inverse}git $gitcommand${reset} in repository ${leadingpath%/*}/${bldred}${curdir##*/}${reset}"
fi
function guardedExecution () {
if $guardedmode; then
echo 1>&2 -n " Execute command here (y/n)? "
read -n 1 -r </dev/tty; echo 1>&2
if [[ $REPLY =~ ^[Yy]$ ]]; then
git "$@"
fi
echo -n "${inverse}git $gitcommand${reset} -> execute here (y/n)? "
read -n 1 -r </dev/tty; echo
if [[ $REPLY =~ ^[Yy]$ ]]; then atomicExecution "$@"; fi
else
git "$@"
atomicExecution "$@"
fi
}
# atomic git command execution with log
function atomicExecution () {
echo "${bldred}->${reset} executing ${inverse}git $gitcommand${reset}" && git "$@"
}
# check if the passed command is known as a core git command
checkGitCommand () {
function checkGitCommand () {
if git help -a | grep -o -q "\b${corecommand}\b"; then
echo 1>&2 "Core command \"$corecommand\" accepted."
echo "Core command \"$corecommand\" accepted."
else
if git config --get-regexp alias | grep -o -q "\.${corecommand} "; then
echo 1>&2 "Alias ${corecommand} accepted."
echo "Alias ${corecommand} accepted."
else
usage && echo 1>&2 "error: unknown GIT command: $corecommand" && exit 1
usage && echo "error: unknown GIT command: $corecommand" && exit 1
fi
fi
}
# check if workspace name is registered
checkWSName () {
while read -r workspace; do
function checkWSName () {
while read workspace; do
parseWsName "$workspace"
if [[ $rwsname == "$wsname" ]]; then return; fi
done <<< "$(listall)"
done <<< "$(echo "$(listall)")"
# when here the ws name was not found
usage && echo 1>&2 "error: unknown workspace name: $wsname" && exit 1
usage && echo "error: unknown workspace name: $wsname" && exit 1
}
# parse out wsname from workspacespec
parseWsName () {
function parseWsName () {
local wsspec="$1"
# Get the workspace value from its specification in the `.gitconfig`.
# May be an absolute path or a variable name of the form: `$VARNAME`
rwsdir=${wsspec#* }
if [[ ${rwsdir:0:1} == '$' ]]; then
# Dereference the `rwsdir` value which is a variable name.
rwsdir_varname=${rwsdir:1}
rwsdir=${!rwsdir_varname}
if [[ -z "${rwsdir}" ]]; then
echo 1>&2 "error: bad environment variable: $rwsdir_varname" && exit 1
fi
fi
rwsname=${wsspec#*.} && rwsname=${rwsname%% *}
}
# detects the wsname of the current directory
wsnameToCurrent () {
while read -r workspace; do
function wsnameToCurrent () {
while read workspace; do
if [ -z "$workspace" ]; then continue; fi
parseWsName "$workspace"
if echo "$PWD" | grep -o -q "$rwsdir"; then wsname="$rwsname" && return; fi
done <<< "$(listall)"
done <<< "$(echo "$(listall)")"
# when here then not in workspace dir
echo 1>&2 "error: you are not in a workspace directory. your registered workspaces are:" && \
wslist="$(listall)" && echo 1>&2 "${wslist:-'<no workspaces defined yet>'}" && exit 1
echo "error: you are not in a workspace directory. your registered workspaces are:" && \
wslist="$(echo "$(listall)")" && echo "${wslist:-'<no workspaces defined yet>'}" && exit 1
}
# helper to check number of arguments.
allowedargcount () {
if [ "$paramcount" -ne "${1:-0}" ] && [ "$paramcount" -ne "${2:-0}" ]; then
function allowedargcount () {
if [ $paramcount -ne $1 ] && [ $paramcount -ne $2 ]; then
echo 1>&2 "error: wrong number of arguments" && usage;
exit 1;
fi
}
# execute the bulk operation
executBulkOp () {
function executBulkOp () {
checkGitCommand
if ! $allwsmode && ! $singlemode; then wsnameToCurrent; fi # by default git bulk works within the 'current' workspace
listall | while read -r workspacespec; do
listall | while read workspacespec; do
parseWsName "$workspacespec"
if [[ -n $wsname ]] && [[ $rwsname != "$wsname" ]]; then continue; fi
cd "$rwsdir" || exit 1
local actual=$PWD
[ "${quiet?}" != "true" ] && echo 1>&2 "Executing bulk operation in workspace ${inverse}$actual${reset}"
# build `find` flags depending on command-line options
local find_flags=()
if [[ "$no_follow_symlinks" == true ]]; then
find_flags+=(-P)
else
find_flags+=(-L)
fi
# find all git repositories under the workspace on which we want to operate
readarray allGitFolders < <(find "${find_flags[@]}" . -name ".git" 2>/dev/null)
for line in "${allGitFolders[@]}"; do
eval cd "\"$rwsdir\""
local actual=$(pwd)
echo "Executing bulk operation in workspace ${inverse}$actual${reset}"
eval find -L . -name ".git" | while read line; do
local gitrepodir=${line::${#line}-5} # cut the .git part of find results to have the root git directory of that repository
cd "$gitrepodir" || exit 1 # into git repo location
local curdir=$PWD
local leadingpath=${curdir#"${actual}"}
# do not execute if we do not want to consider a ".git" directory under a hidden directory
if [ $no_follow_hidden = false ] || ! [[ "$leadingpath" =~ "/." ]]; then
guardedExecution "$@"
fi
cd "$rwsdir" || exit 1 # back to origin location of last find command
eval cd "\"$gitrepodir\"" # into git repo location
local curdir=$(pwd)
local leadingpath=${curdir#${actual}}
echo "Current repository: ${leadingpath%/*}/${bldred}${curdir##*/}${reset}"
guardedExecution "$@"
eval cd "\"$rwsdir\"" # back to origin location of last find command
done
done
}
@ -190,25 +152,20 @@ if [[ $paramcount -le 0 ]]; then usage; fi
# parse command parameters
while [ "${#}" -ge 1 ] ; do
case "$1" in
--quiet|-q) quiet='true' ;;
--listall|--purge)
butilcommand="${1:2}" && break ;;
--removeworkspace|--addcurrent|--addworkspace)
butilcommand="${1:2}" && wsname="$2" && wsdir="$3" && if [ "$4" = "--from" ]; then source="$5"; fi && break ;;
--no-follow-symlinks)
no_follow_symlinks=true ;;
--no-follow-hidden)
no_follow_hidden=true ;;
butilcommand="${1:2}" && wsname="$2" && wsdir="$3" && if [ "$4" == "--from" ]; then source="$5"; fi && break ;;
-a)
allwsmode=true ;;
-g)
guardedmode=true ;;
-w)
singlemode=true && shift && wsname="$1" && checkWSName ;;
--*)
usage && echo 1>&2 "error: unknown argument $1" && exit 1 ;;
-*)
usage && echo 1>&2 "error: unknown argument $1" && exit 1 ;;
--*)
usage && echo 1>&2 "error: unknown argument $1" && exit 1 ;;
*) # git core commands
butilcommand="executBulkOp" && corecommand="$1" && gitcommand="$*" && break ;;
esac && shift
@ -218,7 +175,7 @@ done
if $allwsmode && $singlemode; then echo 1>&2 "error: options -w and -a are incompatible" && exit 1; fi
# if single mode check the supplied workspace name
if $singlemode; then echo 1>&2 "Selected single workspace mode in workspace: $wsname" && checkWSName; fi
if $singlemode; then echo "Selected single workspace mode in workspace: $wsname" && checkWSName; fi
# check right number of arguments
case $butilcommand in

View file

@ -9,15 +9,6 @@ GIT_MERGELOG_FORMAT="$(git config changelog.mergeformat)"
GIT_EDITOR="$(git var GIT_EDITOR)"
PROGNAME="git-changelog"
git_editor() {
if test -z "${GIT_EDITOR:+set}"
then
GIT_EDITOR="$(git var GIT_EDITOR)" || return $?
fi
eval "$GIT_EDITOR" '"$@"'
}
_usage() {
cat << EOF
usage: $PROGNAME options [file]
@ -155,8 +146,6 @@ _fetchCommitRange() {
local start_tag="$2"
local final_tag="$3"
# This shellcheck disable is applied to the whole if-body
# shellcheck disable=SC2086
if [[ "$list_all" == true ]]; then
git log $GIT_LOG_OPTS --pretty=format:"${CUR_GIT_LOG_FORMAT}"
elif [[ -n "$final_tag" && "$start_tag" == "null" ]]; then
@ -244,7 +233,7 @@ commitList() {
# fetch our tags
local _ref _date _tag _tab='%x09'
local _tag_regex='tag: *'
while IFS=$'\t' read -r _ref _date _tag; do
while IFS=$'\t' read _ref _date _tag; do
[[ -z "${_tag}" ]] && continue
# strip out tags form ()
# git v2.2.0+ supports '%D', like '%d' without the " (", ")" wrapping. One day we should use it instead.
@ -291,8 +280,7 @@ commitList() {
for (( i=0; i<"${_tags_list_keys_length}"; i++ )); do
local __curr_tag="${tags_list_keys[$i]}"
local __prev_tag="${tags_list_keys[$i+1]:-null}"
local __curr_date
__curr_date="$(_valueForKeyFakeAssocArray "${__curr_tag}" "${tags_list[*]}")"
local __curr_date="$(_valueForKeyFakeAssocArray "${__curr_tag}" "${tags_list[*]}")"
__curr_date="${__curr_date##*=>}"
# output latest commits, up until the most-recent tag, these are all
@ -388,7 +376,7 @@ _exit() {
# so we need to calculate the total column number(COL_NUM) of header first.
# Why don't we just use the last column?
# Because the body of CMD column may contain space and be treated as multiple fields.
pid_list=( $(ps -f |
pid_list=( $(ps -f |
awk -v ppid=$$ 'NR == 1 {
COL_NUM = NF
}
@ -403,7 +391,7 @@ _exit() {
local _pid
for _pid in "${pid_list[@]}"; do
echo "killing: ${_pid}"
kill -TERM "${_pid}"
kill -TERM ${_pid}
done
wait; stty sane; exit 1
@ -486,10 +474,10 @@ main() {
esac
shift
done
# The default log format unless already set
[[ -z "$CUR_GIT_LOG_FORMAT" ]] && CUR_GIT_LOG_FORMAT="$GIT_LOG_FORMAT"
local _tag="$(_valueForKeyFakeAssocArray "start_tag" "${option[*]}")"
local start_commit="$(_valueForKeyFakeAssocArray "start_commit" "${option[*]}")"
@ -499,6 +487,7 @@ main() {
return 1
fi
start_commit="$start_commit"
start_tag="$(git describe --tags --contains "$start_commit" 2>/dev/null || echo 'null')"
if [[ -z "$start_tag" ]]; then
_error "Could find the associative tag for the start-commit!"
@ -540,10 +529,9 @@ main() {
#
# generate changelog
#
local tmpfile changelog title_tag
tmpfile="$(git_extra_mktemp)"
changelog="$(_valueForKeyFakeAssocArray "output_file" "${option[*]}")"
title_tag="$(_valueForKeyFakeAssocArray "title_tag" "${option[*]}")"
local tmpfile="$(git_extra_mktemp)"
local changelog="$(_valueForKeyFakeAssocArray "output_file" "${option[*]}")"
local title_tag="$(_valueForKeyFakeAssocArray "title_tag" "${option[*]}")"
if [[ "$(_valueForKeyFakeAssocArray "list_style" "${option[*]}")" == true ]]; then
if [[ "$(_valueForKeyFakeAssocArray "list_all" "${option[*]}")" == true ]]; then
@ -562,7 +550,7 @@ main() {
fi
if [[ -z "$changelog" ]]; then
changelog="$(find . -mindepth 1 -maxdepth 1 \( -iname '*change*' -o -iname '*history*' \) | head -n1)"
changelog="$(ls | egrep 'change|history' -i | head -n1)"
if [[ -z "$changelog" ]]; then
changelog="History.md";
fi
@ -581,11 +569,12 @@ main() {
else
cp -f "$tmpfile" "$changelog"
rm -f "$tmpfile"
if [[ -n "$GIT_EDITOR" ]]; then
git_editor "$changelog" || _exit
else
less "$changelog" || _exit
# Use `eval` to handle GIT_EDITOR which contains space and options,
# like ""C:\Program Files (x86)\Notepad++\notepad++.exe" -multiInst ".
# Thanks @JanSchulz to inspire me this solution
[[ -n "$GIT_EDITOR" ]] && eval $GIT_EDITOR "$changelog"
if [[ $? -ne 0 ]]; then
_exit
fi
fi

View file

@ -1,43 +1,7 @@
#!/usr/bin/env bash
PROGNAME="git-clear"
FORCE=0
_usage() {
cat << EOF
usage: $PROGNAME options
usage: $PROGNAME -h|help|?
clear git repository
OPTIONS:
-f, --force Force clear without questioning user
-h, --help, ? Show this message
EOF
}
# Read arguments
while [ "$1" != "" ]; do
case $1 in
-f|--force)
FORCE=1
;;
-h|--help|?)
_usage
exit 1
;;
esac
shift
done
# Only wait for answer if not forced by user
if [[ $FORCE == 0 ]]; then
echo -n "Sure? - THIS COMMAND MAY DELETE FILES THAT CANNOT BE RECOVERED, including those in .gitignore [y/N]: "
read -r clean
else
clean=y
fi
if [ "$clean" = "y" ]; then
git clean -d -f -x && git reset --hard
echo -n "Sure? - This command may delete files that cannot be recovered, including those in .gitignore [y/N]: "
read ans
if [ "$ans" == "y" ]
then git clean -d -f -x && git reset --hard
fi

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
echo -n "Sure? - This command may delete files that cannot be recovered. Files and directories in .gitignore will be preserved [y/N]: "
read -r answer
if [ "$answer" = "y" ]
read ans
if [ "$ans" == "y" ]
then git clean -d -f && git reset --hard
fi

View file

@ -1,36 +1,6 @@
#!/usr/bin/env bash
REF=""
SINCE=""
while [[ $# -gt 0 ]]; do
case "$1" in
-r|--ref)
if [[ -z "$2" ]]; then
echo "error: option $1 requires an argument" >&2
exit 1
fi
REF="$2"
shift
shift
;;
*)
# non-flag args accumulation, e.g. "last " + "week" -> "last week"
SINCE="${SINCE:+$SINCE }$1"
shift
;;
esac
done
if [[ -n "$REF" && -n "$SINCE" ]]; then
echo "error: '--ref <ref>' and '<date>' are mutually exclusive" >&2
exit 1
fi
SINCE="${SINCE:-last week}"
if [[ -n "$REF" ]]; then
git log --pretty='%h %an - %s' "$REF..HEAD"
else
git log --pretty='%h %an - %s' --after="@{$SINCE}"
fi
SINCE="last week"
test $# -ne 0 && SINCE=$@
echo "... commits since $SINCE" >&2
git log --pretty='%an - %s' --after="@{$SINCE}"

View file

@ -1 +0,0 @@
git-abort

View file

@ -5,4 +5,4 @@ if test "$1" = "--all"; then
echo
fi
echo total "$(git rev-list --count HEAD)"
echo total `git rev-list --count HEAD`

View file

@ -32,47 +32,9 @@ elif [[ "$CURRENT_FILENAME" == "" ]]; then
usage
exit 10 # Missing arguments CURRENT_FILENAME
else
if [ -e "$DESTINATION_FILENAME" ]; then
echo 1>&2 "$DESTINATION_FILENAME already exists."
echo 1>&2 "Make sure to remove the destination first."
exit 40
fi
echo "Coping $CURRENT_FILENAME into $DESTINATION_FILENAME"
cp -r "${CURRENT_FILENAME}" "${DESTINATION_FILENAME}"
if [[ "$DESTINATION_FILENAME" == */ ]]; then
echo 1>&2 "$DESTINATION_FILENAME is not a file path."
exit 80
fi
if [[ "$DESTINATION_FILENAME" == */* ]]; then
DESTINATION_DIR="${DESTINATION_FILENAME%/*}"
if ! mkdir -p "$DESTINATION_DIR"; then
echo 1>&2 "Failed to create destination directory: $DESTINATION_DIR"
exit 160
fi
fi
echo "Copying $CURRENT_FILENAME into $DESTINATION_FILENAME"
# Pre-check that the source and destination will work
git mv --dry-run "${CURRENT_FILENAME}" "${DESTINATION_FILENAME}"
# Make a new branch and switch to it
BRANCH_NAME="git-cp-$(date +%s)"
git checkout -b "$BRANCH_NAME"
# Move the original file to the new destination, in this branch
git mv "${CURRENT_FILENAME}" "${DESTINATION_FILENAME}"
git commit -nm "--Duplicate $CURRENT_FILENAME history into $DESTINATION_FILENAME"
# Restore the original file to keep it in the history
git checkout HEAD~ "${CURRENT_FILENAME}"
git commit -nm "--Restore $CURRENT_FILENAME"
# Switch to the original branch and merge this back in.
git checkout -
git merge --no-ff "$BRANCH_NAME" -m "Copy $CURRENT_FILENAME into $DESTINATION_FILENAME"
# We're now done with the branch, so delete it.
# We shouldn't need -D here, as we've already merged it back in.
git branch -d "$BRANCH_NAME"
git add "$DESTINATION_FILENAME"
git commit -m "Duplicate ${CURRENT_FILENAME} history in ${DESTINATION_FILENAME} history." -n
fi

View file

@ -3,7 +3,7 @@
test $# -eq 0 && echo "branch argument required." 1>&2 && exit 1
# preference takes lowest priority; look for remote from prefs first
REMOTE_PREF=$(git config git-extras.create-branch.remote)
REMOTE_PREF=`git config git-extras.create-branch.remote`
if [ -n "$REMOTE_PREF" ]; then
REMOTE=$REMOTE_PREF
fi
@ -39,25 +39,25 @@ then
REMOTE=origin
fi
test -z "$BRANCH" && echo "branch argument required." 1>&2 && exit 1
test -z $BRANCH && echo "branch argument required." 1>&2 && exit 1
if [[ -n $REMOTE ]]
then
stderr=$(git_extra_mktemp)
git ls-remote --exit-code "$REMOTE" 1>/dev/null 2>"$stderr"
git ls-remote --exit-code $REMOTE 1>/dev/null 2>"$stderr"
REMOTE_EXIT=$?
REMOTE_ERROR=$(<"$stderr")
rm -f "$stderr"
if [ $REMOTE_EXIT -eq 0 ]
then
if [[ -n $START_POINT ]]; then
git fetch "$REMOTE"
git checkout --track -b "$BRANCH" "$START_POINT"
git push "$REMOTE" "HEAD:refs/heads/$BRANCH"
git fetch $REMOTE
git checkout --track -b $BRANCH $START_POINT
git push $REMOTE HEAD:refs/heads/$BRANCH
else
git push "$REMOTE" "HEAD:refs/heads/$BRANCH"
git fetch "$REMOTE"
git checkout --track -b "$BRANCH" "$REMOTE/$BRANCH"
git push $REMOTE HEAD:refs/heads/$BRANCH
git fetch $REMOTE
git checkout --track -b $BRANCH $REMOTE/$BRANCH
fi
exit $?
else
@ -70,7 +70,7 @@ fi
if [[ -n $START_POINT ]]
then
git checkout -b "$BRANCH" "$START_POINT"
git checkout -b $BRANCH $START_POINT
else
git checkout -b "$BRANCH"
git checkout -b $BRANCH
fi

View file

@ -2,16 +2,16 @@
set -e
# Assert there is at least one branch provided
test -z "$1" && echo "branch required." 1>&2 && exit 1
test -z $1 && echo "branch required." 1>&2 && exit 1
for branch in "$@"
do
remote=$(git config "branch.$branch.remote" || echo "origin")
ref=$(git config "branch.$branch.merge" || echo "refs/heads/$branch")
remote=$(git config branch.$branch.remote || echo "origin")
ref=$(git config branch.$branch.merge || echo "refs/heads/$branch")
git branch -D "$branch" || true
git branch -D $branch || true
# Avoid deleting local upstream
[ "$remote" = "." ] && continue
git branch -d -r "$remote/$branch" || continue
git push "$remote" ":$ref"
[ "$remote" == "." ] && continue
git branch -d -r $remote/$branch || continue
git push $remote :$ref
done

View file

@ -1,60 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
dry_run=false
force=false
prune=false
while [[ $# -gt 0 ]]; do
case "$1" in
-n|--dry-run)
dry_run=true
shift
;;
-f|--force)
force=true
shift
;;
-p|--prune)
prune=true
shift
;;
*)
echo "Unknown option: $1"
echo "Usage: git delete-gone-branches [-n|--dry-run] [-f|--force] [-p|--prune]"
exit 1
;;
esac
done
if [ "$prune" = true ]; then
git fetch --prune
fi
gone_branches=$(git for-each-ref --format \
'%(if:equals=gone)%(upstream:track,nobracket)%(then)%(refname:short)%(end)' refs/heads/ | sed '/^$/d')
if [ -z "$gone_branches" ]; then
echo "No branches with a gone remote found."
exit 0
fi
if [ "$dry_run" = true ]; then
echo "Would delete the following branches:"
echo "$gone_branches"
exit 0
fi
echo "The following branches will be deleted:"
echo "$gone_branches"
if [ "$force" = false ]; then
read -r -p "Delete these branches? [y/N] " confirm
if [[ ! "$confirm" =~ ^[yY]$ ]]; then
echo "Aborted."
exit 0
fi
fi
echo "$gone_branches" | xargs git branch -D

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
branches=$(git branch --no-color --merged | grep -vE "^(\*|\+)" | grep -v "$(git_extra_default_branch)" | grep -v svn)
branches=$(git branch --no-color --merged | grep -v "\*" | grep -v $(git_extra_default_branch) | grep -v svn)
if [ -n "$branches" ]
then
echo "$branches" | xargs git branch -d
echo "$branches" | xargs -n 1 git branch -d
fi

View file

@ -1,28 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
proceed=false
if [[ $# -gt 0 && ("$1" == "--proceed" || "$1" == "-p") ]]; then
proceed=true
shift
fi
if [[ $# -eq 0 ]]; then
targetBranch=$(git rev-parse --abbrev-ref HEAD)
else
targetBranch=$1
git checkout "$targetBranch"
fi
git for-each-ref refs/heads/ "--format=%(refname:short)" | while read -r branch; do
mergeBase=$(git merge-base "$targetBranch" "$branch")
if [[ $(git cherry "$targetBranch" "$(git commit-tree "$(git rev-parse "$branch^{tree}")" -p "$mergeBase" -m _)") == "-"* ]]; then
if [[ $proceed == true ]]; then
git branch -D "$branch" || true
else
git branch -D "$branch"
fi
fi
done

View file

@ -15,7 +15,7 @@ test ! -f '.gitmodules' && abort 2 '.gitmodules file not found'
NAME="${1%/}"
test -z "$(git config --file='.gitmodules' "submodule.$NAME.url")" \
&& abort 3 'Submodule not found'
&& abort 3 'Submodule not found'
# 1. Handle the .git directory
# 1.a. Delete the relevant section from .git/config

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
# Assert there is at least one tag provided
test -z "$1" && echo "tag required." 1>&2 && exit 1
test -z $1 && echo "tag required." 1>&2 && exit 1
# Detect the default remote exists or not
default_remote=$(git config git-extras.default-remote)
@ -22,7 +22,5 @@ do
done
# Delete all the tags
# shellcheck disable=SC2086
git tag -d $local_tags
# shellcheck disable=SC2086
git push "$origin" $origin_refs
git push $origin $origin_refs

View file

@ -12,4 +12,4 @@ else
fi
fi
git diff --name-only --diff-filter="$filter" "$branch"
git diff --name-only --diff-filter=$filter $branch

View file

@ -59,14 +59,14 @@ active_days() {
color_for() {
if [ "$to_tty" = true ]; then
if [ "$1" -gt 200 ]; then color="$(tputq setaf 1)$(tputq bold)"
elif [ "$1" -gt 150 ]; then color="$(tputq setaf 1)" # red
elif [ "$1" -gt 125 ]; then color="$(tputq setaf 2)$(tputq bold)"
elif [ "$1" -gt 100 ]; then color="$(tputq setaf 2)" # green
elif [ "$1" -gt 75 ]; then color="$(tputq setaf 5)$(tputq bold)"
elif [ "$1" -gt 50 ]; then color="$(tputq setaf 5)" # purplish
elif [ "$1" -gt 25 ]; then color="$(tputq setaf 3)$(tputq bold)"
elif [ "$1" -gt 10 ]; then color="$(tputq setaf 3)" # yellow
if [ $1 -gt 200 ]; then color="$(tputq setaf 1)$(tputq bold)"
elif [ $1 -gt 150 ]; then color="$(tputq setaf 1)" # red
elif [ $1 -gt 125 ]; then color="$(tputq setaf 2)$(tputq bold)"
elif [ $1 -gt 100 ]; then color="$(tputq setaf 2)" # green
elif [ $1 -gt 75 ]; then color="$(tputq setaf 5)$(tputq bold)"
elif [ $1 -gt 50 ]; then color="$(tputq setaf 5)" # purplish
elif [ $1 -gt 25 ]; then color="$(tputq setaf 3)$(tputq bold)"
elif [ $1 -gt 10 ]; then color="$(tputq setaf 3)" # yellow
else color="$(tputq sgr0)" # default color
fi
else
@ -84,38 +84,37 @@ effort() {
local color reset_color commits len dot f_dot i msg active
reset_color=""
test "$to_tty" = true && reset_color="$(tputq sgr0)"
if ! commit_dates=$(dates "$path"); then
exit 255
fi
commit_dates=`dates "$path"`
[ $? -gt 0 ] && exit 255
# Ensure it's not just an empty line
if [ -z "$(head -c 1 <<<"$commit_dates")" ]
if [ -z "`head -c 1 <<<$(echo $commit_dates)`" ]
then
exit 0
fi
commits=$(wc -l <<<"$commit_dates")
commits=`wc -l <<<"$(echo "$commit_dates")"`
color='90'
# ignore <= --above
test "$commits" -le "$above" && exit 0
test $commits -le $above && exit 0
# commits
color_for $(( commits - above ))
color_for $(( $commits - $above ))
len=${#path}
dot="."
f_dot="$path"
i=0 ; while test $i -lt $(( columns - len )) ; do
i=0 ; while test $i -lt $(( $columns - $len )) ; do
f_dot=$f_dot$dot
i=$((i+1))
i=$(($i+1))
done
msg=$(printf " ${color}%s %-10d" "$f_dot" "$commits")
msg=$(printf " ${color}%s %-10d" "$f_dot" $commits)
# active days
active=$(active_days "$commit_dates")
color_for $(( active - above ))
msg="$msg $(printf "${color} %d${reset_color}\n" "$active")"
active=`active_days "$commit_dates"`
color_for $(( $active - $above ))
msg="$msg $(printf "${color} %d${reset_color}\n" $active)"
echo "$msg"
}
@ -137,16 +136,7 @@ sort_effort() {
clear
echo " "
heading
< "$tmp" sort -rn -k 2
}
#
# get processor count, default 8
#
procs() {
if ! (nproc --all || getconf NPROCESSORS_ONLN || getconf _NPROCESSORS_ONLN || grep -c processor /proc/cpuinfo) 2>/dev/null; then
echo 8
fi
< $tmp sort -rn -k 2
}
declare -a paths=()
@ -191,8 +181,8 @@ export args_to_git_log
if test "${#paths}" -eq 0; then
save_ifs=$IFS
IFS=$(echo -en "\n\b")
paths=($(git ls-files))
IFS=`echo -en "\n\b"`
paths=(`git ls-files`)
IFS=$save_ifs
unset save_ifs
fi
@ -213,22 +203,31 @@ export columns
hide_cursor
trap show_cursor_and_cleanup INT
heading
# export functions so subshells can call them
export -f effort
export -f color_for
export -f active_days
export -f dates
export -f tputq
export to_tty
export above
export log_args
bash_params=
# If bash exits successfully with --import-functions,
# then we need to pass it (FreeBSD probably)
bash --import-functions -c ":" 1>/dev/null 2>&1
if [ $? -eq 0 ] ; then
bash_params="--import-functions"
fi
heading
# send paths to effort
nPaths=${#paths[@]}
nProcs=$(procs)
nJobs="\j"
for ((i=0; i<nPaths; ++i))
do
while (( ${nJobs@P} >= nProcs )); do
wait -n
done
effort "${paths[i]}" &
done|tee "$tmp"
printf "%s\0" "${paths[@]}" | xargs -0 -n 1 -P 4 -I % bash $bash_params -c "effort \"%\"" | tee $tmp
# if more than one path, sort and print
test "$(wc -l "$tmp" | awk '{print $1}')" -gt 1 && sort_effort
test "$(wc -l $tmp | awk '{print $1}')" -gt 1 && sort_effort
echo
show_cursor_and_cleanup

View file

@ -1,10 +1,10 @@
#!/usr/bin/env bash
VERSION="7.6.0-dev"
INSTALL_SCRIPT="https://raw.githubusercontent.com/tj/git-extras/main/install.sh"
VERSION="6.2.0"
INSTALL_SCRIPT="https://raw.githubusercontent.com/tj/git-extras/master/install.sh"
update() {
local bin="$(command -v git-extras)"
local bin="$(which git-extras)"
local prefix=${bin%/*/*}
local orig=$PWD
@ -14,10 +14,10 @@ update() {
}
updateForWindows() {
local bin="$(command -v git-extras)"
local bin="$(which git-extras)"
local prefix=${bin%/*/*}
local orig=$PWD
# we need to clean up /tmp manually on windows
cd /tmp \
&& rm -rf ./git-extras \

View file

@ -6,30 +6,22 @@ if [ -z "$branch_prefix" ]; then
branch_prefix="feature"
fi
branch_separator=$(git config --get git-extras.feature.separator)
if [ -z "$branch_separator" ]; then
branch_separator="/"
fi
merge_mode="--no-ff"
finish=false
declare -a argv
while test $# != 0
do
case $1 in
-a|--alias )
if [[ -n $2 ]] && [[ $2 != -- ]]
if [[ -n $2 ]]
then
shift # shift -a|-alias
branch_prefix=$1
else
echo >&2 "option $1 requires a value"
exit 1
argv+=($1) # treat tail '-a' as <name>
fi
;;
-r|--remote )
if [[ -n $2 ]] && [[ $2 != -- ]]
if [[ -n $2 ]]
then
remote=$2
shift
@ -37,16 +29,6 @@ do
remote="origin"
fi
;;
-s|--separator )
if [[ -n $2 ]] && [[ $2 != -- ]]
then
branch_separator=$2
shift
else
echo >&2 "option $1 requires a value"
exit 1
fi
;;
--squash )
merge_mode="--squash"
;;
@ -54,17 +36,8 @@ do
start_point=$2
shift
;;
-- )
# terminate argument parsing
shift
argv+=("$@")
break
;;
finish )
finish=true
;;
* )
argv+=("$1")
argv+=($1)
;;
esac
shift
@ -72,34 +45,38 @@ done
concatargs() {
str=$(IFS='-'; echo "$*")
branch="$branch_prefix$branch_separator$str"
branch="$branch_prefix"/$str
}
test -z "${argv[0]}" && echo "$branch_prefix" "<name> required." 1>&2 && exit 1
concatargs "${argv[@]}"
if "${finish}"
then
if test "${argv[0]}" = "finish"; then
test -z "${argv[1]}" && echo "$branch_prefix" "<name> required." 1>&2 && exit 1
branch="$branch_prefix"/"${argv[1]}"
git merge ${merge_mode} "$branch" && git delete-branch "$branch"
else
test -z "${argv[0]}" && echo "$branch_prefix" "<name> required." 1>&2 && exit 1
if test -n "${argv[1]}"; then
concatargs "${argv[@]}"
else
branch="$branch_prefix"/"${argv[0]}"
fi
if [[ -n $remote ]] && [[ -z $start_point ]]
then
git create-branch -r "$remote" "$branch"
git create-branch -r $remote $branch
fi
if [[ -z $remote ]] && [[ -z $start_point ]]
then
git create-branch "$branch"
git create-branch $branch
fi
if [[ -n $remote ]] && [[ -n $start_point ]]
then
git create-branch -r "$remote" --from "$start_point" "$branch"
git create-branch -r $remote --from $start_point $branch
fi
if [[ -z $remote ]] && [[ -n $start_point ]]
then
git create-branch --from "$start_point" "$branch"
git create-branch --from $start_point $branch
fi
fi

View file

@ -63,21 +63,21 @@ main() {
if [ -d "${destination_path}/.git" ]; then
(
cd "${destination_path}"
cd ${destination_path}
# Delete all remotes
for remote in $(git remote); do
git remote rm "${remote}"
for remote in `git remote`; do
git remote rm ${remote}
done
# Add origin
git remote add origin "${remote_url}"
git remote add origin ${remote_url}
git fetch origin
# Set default branch
if [ -z "${branch:-}" ]; then
branch=$(LC_ALL=C git remote show origin | grep -oP '(?<=HEAD branch: )[^ ]+$')
git remote set-head origin "${branch}"
branch=`LC_ALL=C git remote show origin | grep -oP '(?<=HEAD branch: )[^ ]+$'`
git remote set-head origin ${branch}
else
git remote set-head origin -a
fi
@ -87,20 +87,19 @@ main() {
git reset --hard HEAD
# Get on the desired branch
git checkout "${branch}"
git reset --hard "origin/${branch}"
git checkout ${branch}
git reset --hard origin/${branch}
# Delete all other branches
# shellcheck disable=SC2063
branches=$(git branch | grep -v '*' | xargs)
branches=`git branch | grep -v \* | xargs`
if [ -n "${branches}" ]; then
git branch -D "${branches}"
git branch -D ${branches}
fi
)
elif [ -n "${branch:-}" ]; then
git clone -b "${branch}" "${remote_url}" "${destination_path}"
git clone -b ${branch} ${remote_url} ${destination_path}
else
git clone "${remote_url}" "${destination_path}"
git clone ${remote_url} ${destination_path}
fi
}

View file

@ -12,18 +12,16 @@ test -z "$url" && abort "github repo needs to be specified as an argument"
# validate user
echo "Enter your github username"
read -r user
read user
[ -n "$user" ] || abort "git username required"
# personal access token
# config name is github-personal-access-token '_' is not allowed in git config
github_personal_access_token=$(git config --default "$GITHUB_TOKEN" git-extras.github-personal-access-token)
test -z "$github_personal_access_token" && abort "GITHUB_TOKEN, or git config git-extras.github-personal-access-token required"
echo "Enter github password for user \"$user\""
read -s passwd
echo "Enter github two-factor authentication code (leave blank if not set up)"
read MFA_CODE
# extract owner + project from repo url
project=${url##*/}
owner=${url%/"$project"}
owner=${url%/$project}
project=${project%.git}
if [[ $owner == git@* ]]; then
owner=${owner##*:}
@ -32,20 +30,19 @@ else
fi
# validate
[[ -z "$project" || -z "$owner" ]] && abort "github repo needs to be specified as an argument"
[ -z "$project" -o -z "$owner" ] && abort "github repo needs to be specified as an argument"
# create fork
if ! curl -qsf \
curl -qsf \
-X POST \
-u "$user:$github_personal_access_token" \
-u "$user:$passwd" \
-H "X-GitHub-OTP: $MFA_CODE" \
"https://api.github.com/repos/$owner/$project/forks"
then
abort "fork failed"
fi
[ $? = 0 ] || abort "fork failed"
echo "Add GitHub remote branch via SSH (you will be prompted to verify the server's credentials)? (y/n)"
read -r use_ssh
read use_ssh
# Check if user has ssh configured with GitHub
if [ -n "$use_ssh" ] && ssh -T git@github.com 2>&1 | grep -qi 'success'; then
remote_prefix="git@github.com:"
@ -61,7 +58,7 @@ else
# clone forked repo into current dir
git clone "${remote_prefix}${user}/${project}.git" "$project"
# add reference to origin fork so can merge in upstream changes
cd "$project" || exit
cd "$project"
git remote add upstream "${remote_prefix}${owner}/${project}.git"
git fetch upstream
fi

View file

@ -2,19 +2,19 @@
branch=$1
test -z "$branch" && echo "branch required." 1>&2 && exit 1
test -z $branch && echo "branch required." 1>&2 && exit 1
changes=$(git status --porcelain)
changes=`git status --porcelain`
clean()
{
git symbolic-ref HEAD "refs/heads/$branch"
git symbolic-ref HEAD refs/heads/$branch
rm .git/index
git clean -fdx
}
if [ -n "$changes" ]; then
read -rp "All untracked changes will be lost. Continue [y/N]? " res
if [ ! -z "$changes" ]; then
read -p "All untracked changes will be lost. Continue [y/N]? " res
case $res in
[Yy]* ) ;;
* ) exit 0;;

View file

@ -1,40 +0,0 @@
#!/usr/bin/env bash
_usage() {
printf '%s\n' "usage: ${0##*/} <url>
usage: ${0##*/} --help
Clone a repository in a particular directory."
}
if (( $# == 0 )); then
_usage
exit 0
fi
for arg; do
if [ "$arg" = '-h' ] || [ "$arg" = '--help' ]; then
_usage
exit 0
fi
done
url=$1
if ! shift; then
printf 'ERROR: Failed to shift' >&2
exit 1
fi
clone_path=$(git config --get git-extras.get.clone-path)
if [ -z "$clone_path" ]; then
printf 'ERROR: %s\n' "Git configuration key 'git-extras.get.clone-path' must be set to a directory to clone under" >&2
exit 1
fi
dirname=${url%/}
dirname=${dirname%.git}
dirname=${dirname##*/}
mkdir -p "$clone_path"
git clone "$url" "$clone_path/$dirname" "$@"

View file

@ -4,10 +4,10 @@ echo 'setting up gh-pages'
echo '-------------------'
echo 'Tell me your github account username: '
read -r username
read username
echo 'Now, tell me your repository name: '
read -r repository
read repository
git stash \
&& git checkout -b 'gh-pages' \

View file

@ -3,9 +3,9 @@
src=$1
dst=$2
test -z "$src" && echo "source branch required." 1>&2 && exit 1
test -z "$dst" && echo "destination branch required." 1>&2 && exit 1
test -z $src && echo "source branch required." 1>&2 && exit 1
test -z $dst && echo "destination branch required." 1>&2 && exit 1
git checkout "$dst" \
&& git merge --no-ff "$src" \
&& git branch -d "$src"
git checkout $dst \
&& git merge --no-ff $src \
&& git branch -d $src

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
for param in "$@"
for param in $*
do
case $param in
-h)
@ -31,7 +31,7 @@ do
esac
done
cd "$(git-root)" || exit # cd for git blame
cd "$(git-root)" # cd for git blame
MERGED_LOG=$(git_extra_mktemp)
if [[ $EMAIL == '-e' ]]
then
@ -44,13 +44,11 @@ for file in $(git diff --name-only "$@")
do
test -n "$DEBUG" && echo "git blame $file"
# $1 - since $2 - until
# shellcheck disable=SC2086
git blame $NOT_WHITESPACE --line-porcelain "$1" -- "$file" 2> /dev/null |
LC_ALL=C sed -n "$PATTERN" | sort | uniq -c | LC_ALL=C sed 's/^\(.\)/- \1/' >> "$MERGED_LOG"
git blame $NOT_WHITESPACE --line-porcelain "$1" -- "$file" 2> /dev/null |
LC_ALL=C sed -n "$PATTERN" | sort | uniq -c | LC_ALL=C sed 's/^\(.\)/- \1/' >> $MERGED_LOG
# if $2 not given, use current commit as "until"
# shellcheck disable=SC2086
git blame $NOT_WHITESPACE --line-porcelain "${2-@}" -- "$file" 2> /dev/null |
LC_ALL=C sed -n "$PATTERN" | sort | uniq -c | LC_ALL=C sed 's/^\(.\)/+ \1/' >> "$MERGED_LOG"
LC_ALL=C sed -n "$PATTERN" | sort | uniq -c | LC_ALL=C sed 's/^\(.\)/+ \1/' >> $MERGED_LOG
done
DEBUG="$DEBUG" awk '
@ -73,8 +71,8 @@ END {
printf("%d %s\n", contributors[people], people)
}
}
}' "$MERGED_LOG" | sort -nr | # only gawk supports built-in sort function
while read -r line
}' $MERGED_LOG | sort -nr | # only gawk supports built-in sort function
while read line
do
people=${line#* }
num=${line%% *}
@ -89,7 +87,7 @@ do
do
printf "+"
done
printf "(%s)" "$num"
printf "(%s)" $num
else
for (( i = 0; i < num; i++ ))
do
@ -105,7 +103,7 @@ do
do
printf "-"
done
printf "(%s)" "$num"
printf "(%s)" $num
else
for (( i = 0; i > num; i-- ))
do

View file

@ -1,28 +1,8 @@
#!/usr/bin/env bash
GIT_DIR=$(git rev-parse --git-dir 2>/dev/null)
: ${GIT_DIR:=$(git rev-parse --git-dir)}
# awk script that takes 2 input files. The first one is newline deilmeted
# string of patterns to look for, second one is the file to remove them from.
# outfile has to be passed with -v upon call and is the file result is
# written to.
read -r -d '' AWK_SCRIPT <<'EOF'
# process the first "file" (newline split argument list)
NR==FNR { a[b++]=$0; next; }
# process file
{
found=0;
for (i=0; i != b; i++) {
if (a[i] == $0) { found=1; }
}
if (found == 1) { print "... removing '"$0"'"; }
else { print $0 > outfile }
}
EOF
show_contents() {
function show_contents {
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
echo "$1 gitignore: $2" && cat "$file"
@ -31,41 +11,18 @@ show_contents() {
fi
}
cd_to_git_root() {
local error_level="$1"
if ! git rev-parse --git-dir &>/dev/null; then
if [ "$error_level" = '--warn' ]; then
echo "Warning: Not currently in a Git repository" >&2
elif [ "$error_level" = '--error' ]; then
echo "Error: Not currently in a Git repository" >&2
exit 1
fi
fi
local result=
if result=$(git rev-parse --show-toplevel 2>/dev/null); then
cd "$result" || exit
fi
function global_ignore() {
git config --global core.excludesile || \
([ -n "$XDG_CONFIG_HOME" ] && echo "$XDG_CONFIG_HOME/git/ignore") || \
echo "$HOME/.config/git/ignore"
}
global_ignore() {
if ! git config --global core.excludesFile 2>/dev/null; then
if [ -f "$HOME/.gitignore" ]; then
echo "$HOME/.gitignore"
else
echo "${XDG_CONFIG_HOME:-$HOME/.config}/git/ignore"
fi
fi
}
show_global() {
function show_global {
show_contents Global "$(global_ignore)"
}
add_global() {
local global_gitignore
global_gitignore="$(global_ignore)"
function add_global {
local global_gitignore="$(global_ignore)"
if [ -z "$global_gitignore" ]; then
echo "Can't find global .gitignore."
echo ""
@ -76,104 +33,36 @@ add_global() {
fi
}
show_local() {
cd_to_git_root --warn
function show_local {
cd "$(git root)"
show_contents Local .gitignore
}
add_local() {
cd_to_git_root --warn
function add_local {
cd "$(git root)"
add_patterns .gitignore "$@"
}
show_private() {
cd_to_git_root --error
function show_private {
cd "$(git root)"
show_contents Private "${GIT_DIR}/info/exclude"
}
add_private() {
cd_to_git_root --error
function add_private {
cd "$(git root)"
test -d "${GIT_DIR}/info" || mkdir -p "${GIT_DIR}/info"
add_patterns "${GIT_DIR}/info/exclude" "$@"
}
add_patterns() {
function add_patterns {
echo "Adding pattern(s) to: $1"
local file="${1/#~/$HOME}"
dir_name=$(dirname "$file")
if [ ! -d "$dir_name" ]; then
mkdir -p "$dir_name"
fi
if [ -s "$file" ]; then
# If the content of $file doesn't end with a newline, add one
test "$(tail -c 1 "$file")" != "" && echo "" >> "$file"
fi
for pattern in "${@:2}"; do
echo "... adding '$pattern'"
(test -f "$file" && test "$pattern" && grep -q -F -x -- "$pattern" "$file") || echo "$pattern" >> "$file"
done
}
edit_file() {
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
echo "Editing $1 gitignore: ($2)" && eval "$(git var GIT_EDITOR) $(printf '%q' "$file")"
echo "Done."
else
echo "There is no $1 .gitignore yet." >&2
exit 1
fi
}
_usage() {
cat << EOF
Usage: git ignore [OPTION]... [PATTERN]...
Modify or display local global or private gitignore files.
OPTIONs set context (local, global, private) and action (display, add,
remove, edit). In case of collision, last flag overwrites preceding ones.
Defaults are: local context, action is display (see man git ignore for
more details).
Context examples:
local: .../repo/.gitignore
private: .../repo/.git/info/exclude
global: \$HOME/.gitignore
PATTERNs are the gitignore patterns as specified in git documentation.
Options:
-l, --local Set context to local gitignore
-g, --global Set context to global gitignore
-p, --private Set context to private gitignore
-e, --edit Set action to edit
-r, --remove Set action to remove
-h, --help Print this message
-- End of options delimiter
EOF
}
remove_patterns() {
declare -a args
local tmpfile
args=( "${@:3}" )
local file="${2/#~/$HOME}"
if [ -f "$file" ]; then
tmpfile="$(mktemp -q "${TMPDIR:-/tmp}"/git-extras-ignore.XXXXXX 2>/dev/null)"
echo "Removing patterns from $1 gitignore: $2"
awk -v outfile="$tmpfile" "${AWK_SCRIPT}"\
<(printf '%s\n' "${args[@]}") "$file"
cat "$tmpfile" > "$file"
rm "$tmpfile"
else
echo "There is no $1 .gitignore yet"
exit 1
fi
}
# can have only 1 action and 1 level, if conflicting flags are passed
# latter ones overwrite former
# sanity of args not tested (e.g. there should be no args if -e is supplied)
if test $# -eq 0; then
show_global
echo "---------------------------------"
@ -181,105 +70,22 @@ if test $# -eq 0; then
echo "---------------------------------"
show_private
else
# parse flags and args
level="none"
action="none"
declare -a args
while [ $# -gt 0 ]; do
case "$1" in
-h|--help)
_usage
exit 0
;;
-l|--local)
level="local"
;;
-g|--global)
level="global"
;;
-p|--private)
level="private"
;;
-e|--edit)
action="edit"
;;
-r|--remove)
action="remove"
;;
--)
shift
args+=("$@")
break
;;
*)
args+=("$1")
;;
esac
shift
done
# compatible with previous version
if [ "$action" = "none" ]; then
case "$level" in
local)
test ${#args[@]} -ne 0 && add_local "${args[@]}" && echo
show_local
;;
global)
test ${#args[@]} -ne 0 && add_global "${args[@]}" && echo
show_global
;;
private)
test ${#args[@]} -ne 0 && add_private "${args[@]}" && echo
show_private
;;
none)
add_local "${args[@]}"
# maybe show_local here too?
;;
esac
exit 0
# open file in editor
elif [ "$action" = "edit" ]; then
case "$level" in
local|none)
cd_to_git_root --warn
edit_file 'local' .gitignore && echo
;;
global)
global_gitignore="$(global_ignore)"
edit_file global "$global_gitignore" && echo
;;
private)
cd_to_git_root --error
test -d "${GIT_DIR}/info" || mkdir -p "${GIT_DIR}/info"
edit_file private "${GIT_DIR}/info/exclude" && echo
;;
esac
exit 0
# remove entries
else
if [ ${#args[@]} -eq 0 ]; then
echo "Nothing to remove."
exit 0
fi
case "$level" in
local|none)
cd_to_git_root --warn
remove_patterns 'local' .gitignore "${args[@]}" && echo
show_local
;;
global)
global_gitignore="$(global_ignore)"
remove_patterns global "$global_gitignore" "${args[@]}" && echo
show_global
;;
private)
cd_to_git_root --error
remove_patterns private "${GIT_DIR}/info/exclude" "${args[@]}" && echo
show_private
;;
esac
exit 0
fi
case "$1" in
-l|--local)
test $# -gt 1 && add_local "${@:2}" && echo
show_local
;;
-g|--global)
test $# -gt 1 && add_global "${@:2}" && echo
show_global
;;
-p|--private)
test $# -gt 1 && add_private "${@:2}" && echo
show_private
;;
*)
add_local "$@"
;;
esac
fi

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
gitignore_io_url="https://www.toptal.com/developers/gitignore/api/"
gitignore_io_url="https://www.gitignore.io/api/"
default_path="$HOME/.gi_list"
if [[ -n "$XDG_CACHE_HOME" ]]; then
default_path="$XDG_CACHE_HOME/git-extras/gi_list"
@ -17,7 +17,7 @@ print_in_alphabetical_order() {
for ignorable in $(echo "$gi_list" | sort);
do
first_character=${ignorable:0:1}
if [[ $first_character = "$previous_first_character" ]]; then
if [[ $first_character = $previous_first_character ]]; then
printf " %s" "$ignorable"
elif [[ $first = true ]]; then
previous_first_character=$first_character
@ -46,11 +46,12 @@ search() {
}
print_last_modified_time() {
if ! gi_list_date=$(stat -c "%y" "$default_path" 2> /dev/null); then
if ! gi_list_date=$(stat -f "%t%Sm" "$default_path" 2> /dev/null); then
if ! gi_list_date=$(date -r "$default_path" +%s 2> /dev/null); then
gi_list_date=0
fi
gi_list_date=$(stat -c "%y" "$default_path" 2> /dev/null)
if [ "$?" -ne 0 ]; then
gi_list_date=$(stat -f "%t%Sm" "$default_path" 2> /dev/null)
if [ "$?" -ne 0 ]; then
gi_list_date=$(date -r "$default_path" +%s 2> /dev/null)
[ "$?" -ne 0 ] && gi_list_date=0
fi
fi
echo "Last update time: $gi_list_date"
@ -84,7 +85,7 @@ show_usage() {
check_list_exist() {
if ! [ -f "$default_path" ]; then
echo "-----Initial gitignore.io list----"
update_gi_list
update_gi_list &
echo "-----Save to $default_path-----"
echo
fi

View file

@ -65,7 +65,7 @@ echon "${COLOR_TITLE}## Local Branches:${NORMAL}"
echon "$(local_branches)"
SUBMODULES_LOG=$(submodules)
if [ -n "$SUBMODULES_LOG" ]; then
if [ ! -z "$SUBMODULES_LOG" ]; then
echon "${COLOR_TITLE}## Submodule(s):${NORMAL}"
echon "$SUBMODULES_LOG"
fi
@ -73,7 +73,7 @@ fi
echon "${COLOR_TITLE}## Most Recent Commit:${NORMAL}"
echon "$(most_recent_commit)"
if [ -n "$HIDE_CONFIG" ]; then
if [ ! -z "$HIDE_CONFIG" ]; then
echon "${COLOR_TITLE}## Configuration (.git/config):${NORMAL}"
echon "$(get_config)"
fi

View file

@ -1,3 +1,6 @@
#!/usr/bin/env bash
git log "@{upstream}..@" "$@"
ref=$(git symbolic-ref HEAD)
branch=${ref#refs/heads/}
git log origin/${branch}..${branch} $*

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash
filename="$1"
test -z "$filename" && echo "filename required." 1>&2 && exit 1
git update-index --skip-worktree "$filename"
filename=$1
test -z $filename && echo "filename required." 1>&2 && exit 1
git update-index --skip-worktree $filename

View file

@ -1,87 +0,0 @@
#!/usr/bin/env bash
# Bash unofficial strict mode
set -eo pipefail
IFS=$'\n\t'
cd "$(git rev-parse --show-toplevel)"
USAGE='git-magic [-a] [-m msg] [-e] [-p] [-f]'
ALL=false
PUSH=false
FORCE=''
ARGS=()
while getopts "m:eapfh" arg; do
case "${arg}" in
m)
ARGS+=("-m")
ARGS+=("${OPTARG}")
;;
e)
ARGS+=("-e")
;;
a)
ALL=true
;;
p)
PUSH=true
;;
f)
FORCE='--force-with-lease'
;;
h)
echo "$USAGE"
exit 0
;;
?)
echo "${USAGE}"
exit 1
;;
esac
done
shift $((OPTIND-1))
if [[ $# != 0 ]]; then
echo "Unknown arguments: $*"
echo "${USAGE}"
exit 1
fi
set -- "${ARGS[@]}" # restore positional parameters
if [[ $ALL == true ]]; then
# Check if there is no changes to stage
if [[ -z $(git status --porcelain) ]]; then
echo "No changes to commit"
exit 0
fi
# Get confirmation from user
git status
echo "Everything will be added"
read -rp "Press enter to continue"
# Restore staging area so that, for example,
# add and modify will not be separate entries in status
git restore --staged . || true
git add .
fi
# Commit with generated message
git commit --no-edit "$@" -m "$(git status --porcelain -uno)"
if [[ $PUSH == true ]]; then
git push $FORCE
fi
# --no-edit by default. use option -e to override this
# Arguments are passed with quoted "$@" to avoid misparsing
# Generated message comes after user provided arguments
# so that user can insert title before it

View file

@ -18,7 +18,7 @@ then
git stash
fi
if [ "${!#}" = '--ff-only' ]; then
if [ "${!#}" == '--ff-only' ]; then
case $# in
2 ) # dest --ff
git push "$(git rev-parse --show-toplevel)" "$cur_branch":"$1";;

View file

@ -5,7 +5,7 @@ branch=$2
prefix=$3
flat=0
if test "$prefix" = "."; then
if test $prefix = "."; then
prefix=$(mktemp -u 'git-merge-repo.XXXXXXX')
flat=1
fi
@ -16,10 +16,10 @@ message=$(git log -1 --pretty=%B)
if test $flat -eq 1; then
git stash -u
mv -i "$prefix"/* ./
mv -i $prefix/* ./
git undo
git add .
git commit -am "$message"
git stash apply
rm -drf "$prefix"
rm -drf $prefix
fi

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
usage() {
echo 1>&2 "usage: git missing [<first branch>] <second branch> [<git log options>] [[--] <path>...]"
echo 1>&2 "usage: git missing [<first branch>] <second branch> [<git log options>]"
}
if [ "${#}" -lt 1 ]
@ -12,20 +12,9 @@ fi
declare -a git_log_args=()
declare -a branches=()
declare -a pathspec=()
declare parse_path=false
for arg in "$@" ; do
if [[ $parse_path == true ]]; then
pathspec+=("$@")
break
fi
case "$arg" in
--)
parse_path=true
;;
--*)
git_log_args+=( "$arg" )
;;
@ -49,4 +38,4 @@ else
exit 1
fi
git log "${git_log_args[@]}" "$firstbranch"..."$secondbranch" --format="%m %h %s" --left-right -- "${pathspec[@]}"
git log "${git_log_args[@]}" "$firstbranch"..."$secondbranch" --format="%m %h %s" --left-right

View file

@ -7,30 +7,22 @@ if [ -z "${1-}" ] ; then
exit 1
fi
remote_ref_kind=merge-requests
if test "$1" = "clean"; then
git for-each-ref refs/heads/mr/* --format='%(refname)' | while read -r ref; do
git branch -D "${ref#refs/heads/}"
git for-each-ref refs/heads/mr/* --format='%(refname)' | while read ref; do
git branch -D ${ref#refs/heads/}
done
exit 0
elif [[ $1 =~ ^(https?://[^/]+/(.+))/merge_requests/([0-9]+).*$ ]]; then
remote=${BASH_REMATCH[1]}.git
id=${BASH_REMATCH[3]}
elif [[ $1 =~ ^(https?://[^/]+/(.+))/pulls/([0-9]+).*$ ]]; then
# Forgejo/Codeberg pull request URL, e.g.
# https://codeberg.org/owner/repository/pulls/453
remote=${BASH_REMATCH[1]}.git
id=${BASH_REMATCH[3]}
remote_ref_kind=pull
else
id=$1
remote=${2:-origin}
fi
branch=mr/$id
remote_ref=refs/$remote_ref_kind/$id/head
git fetch -fu "$remote" "$remote_ref:$branch"
git checkout "$branch"
git config --local --replace "branch.$branch.merge" "$remote_ref"
git config --local --replace "branch.$branch.remote" "$remote"
remote_ref=refs/merge-requests/$id/head
git fetch -fu $remote $remote_ref:$branch
git checkout $branch
git config --local --replace branch.$branch.merge $remote_ref
git config --local --replace branch.$branch.remote $remote

View file

@ -9,15 +9,15 @@ do
file="$file"' '"$i"
shift
done
test -n "$*" && range=("$@")
test -n "$*" && range="$*"
test -z "$file" && echo "file required." 1>&2 && exit 1
if [ -z "${range[*]}" ]
if [ -z "$range" ]
then
git filter-branch -f --index-filter "git rm -r --cached ""$file"" --ignore-unmatch" \
--prune-empty --tag-name-filter cat -- --all
else
# $range is an array so that we can forward multiple rev-list arguments
# don't quote $range so that we can forward multiple rev-list arguments
git filter-branch -f --index-filter "git rm -r --cached ""$file"" --ignore-unmatch" \
--prune-empty --tag-name-filter cat -- "${range[@]}"
--prune-empty --tag-name-filter cat -- $range
fi

View file

@ -2,7 +2,7 @@
set -e
set -o pipefail
if ! command -v pastebinit &>/dev/null; then
if ! command -v pastebinit >/dev/null 2>&1; then
echo >&2 "To run 'git paste', you need to install pastebinit in your system"
exit 1
fi

View file

@ -12,10 +12,10 @@ pull() {
ref="refs/pull/$id/merge"
fi
git fetch -fu "$remote" "$ref:$branch" && \
git checkout "$branch" && \
git config --local --replace "branch.$branch.merge" "$ref" && \
git config --local --replace "branch.$branch.remote" "$remote"
git fetch -fu $remote $ref:$branch && \
git checkout $branch && \
git config --local --replace branch.$branch.merge $ref && \
git config --local --replace branch.$branch.remote $remote;
}
pull_pr_if_matched() {
@ -54,8 +54,8 @@ done
test -z "$1" && echo "pr number required." 1>&2 && exit 1
if test "$1" = "clean"; then
git for-each-ref refs/heads/pr/* --format='%(refname)' | while read -r ref; do
git branch -D "${ref#refs/heads/}"
git for-each-ref refs/heads/pr/* --format='%(refname)' | while read ref; do
git branch -D ${ref#refs/heads/}
done
elif [[ "$1" =~ ^[0-9]+$ ]]; then

View file

@ -5,7 +5,7 @@ SECONDARY_BRANCH=""
FF="--ff"
CONTINUE="no"
current_branch() {
function current_branch() {
git rev-parse --abbrev-ref HEAD
}
@ -19,10 +19,10 @@ function usage()
echo " -c|--continue: Continue after the user updates conflicts."
}
while [[ $# -gt 0 ]]
while [[ $# > 0 ]]
do
key="$1"
case $key in
--no-ff)
FF="--no-ff"
@ -50,17 +50,19 @@ fi
if [[ "$CONTINUE" == "yes" ]]; then
TARGET_BRANCH=$(current_branch)
SECONDARY_BRANCH=${TARGET_BRANCH%"-rebased-on-top-of-"*}
PRIMARY_BRANCH=${TARGET_BRANCH#*"-rebased-on-top-of-"}
if [[ "${SECONDARY_BRANCH}-rebased-on-top-of-${PRIMARY_BRANCH}" != $TARGET_BRANCH ]]; then
set $(echo "$TARGET_BRANCH" | sed -e "s/-rebased-on-top-of-/\n/g")
if [[ $# != 2 ]]; then
echo "Couldn't continue rebasing on ${TARGET_BRANCH}"
exit 30 # Impossible to detect PRIMARY_BRANCH AND SECONDARY_BRANCH
fi
SECONDARY_BRANCH=$1
PRIMARY_BRANCH=$2
echo "Continuing rebasing of $SECONDARY_BRANCH on top of $PRIMARY_BRANCH"
git commit || exit 51
git branch -d "${SECONDARY_BRANCH}" || exit 52
git branch -m "${TARGET_BRANCH}" "${SECONDARY_BRANCH}" || exit 53
git branch -d ${SECONDARY_BRANCH} || exit 52
git branch -m ${TARGET_BRANCH} ${SECONDARY_BRANCH} || exit 53
elif [[ "$PRIMARY_BRANCH" == "" ]]; then
usage
@ -69,13 +71,14 @@ else
echo "Rebasing $SECONDARY_BRANCH on top of $PRIMARY_BRANCH"
TARGET_BRANCH="${SECONDARY_BRANCH}-rebased-on-top-of-${PRIMARY_BRANCH}"
git checkout "${PRIMARY_BRANCH}" || exit 41
git checkout -b "${TARGET_BRANCH}" || exit 42
git checkout ${PRIMARY_BRANCH} || exit 41
git checkout -b ${TARGET_BRANCH} || exit 42
git merge ${SECONDARY_BRANCH} ${FF} \
-m "Psycho-rebased branch ${SECONDARY_BRANCH} on top of ${PRIMARY_BRANCH}"
if git merge "${SECONDARY_BRANCH}" ${FF} \
-m "Psycho-rebased branch ${SECONDARY_BRANCH} on top of ${PRIMARY_BRANCH}"; then
git branch -d "${SECONDARY_BRANCH}" || exit 43
git branch -m "${TARGET_BRANCH}" "${SECONDARY_BRANCH}" || exit 44
if [[ $? == 0 ]]; then
git branch -d ${SECONDARY_BRANCH} || exit 43
git branch -m ${TARGET_BRANCH} ${SECONDARY_BRANCH} || exit 44
else
echo "Resolve the conflict and run ``${PROGRAM} --continue``."
exit 1

View file

@ -31,9 +31,9 @@ EOF
# personal access token
# config name is github-personal-access-token '_' is not allowed in git config
github_personal_access_token=$(git config --default "$GITHUB_TOKEN" git-extras.github-personal-access-token)
github_personal_access_token=$(git config git-extras.github-personal-access-token)
test -z "$github_personal_access_token" && abort "GITHUB_TOKEN or git config git-extras.github-personal-access-token required"
test -z "$github_personal_access_token" && abort "git config git-extras.github-personal-access-token required"
# branch
@ -43,7 +43,7 @@ if [ -z "$remote" ]; then
echo 'no upstream found, push to origin as default'
remote="origin"
fi
[ "$remote" = "." ] && abort "the upstream should be a remote branch."
[ "$remote" == "." ] && abort "the upstream should be a remote branch."
# make sure it's pushed
@ -72,7 +72,7 @@ echo
if [ -z "$base" ]
then
base="$(git_extra_default_branch)"
base="master"
fi
body=$(json "$title" "$body" "$branch" "$base")
@ -82,4 +82,4 @@ curl \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $github_personal_access_token" \
-H "X-GitHub-OTP: $mfa_code" \
"https://api.github.com/repos/$project/pulls" -d "$body"
"https://api.github.com/repos/$project/pulls" -d "$body"

View file

@ -17,26 +17,26 @@ fi
# Use a temporary index.
index=$(git_extra_mktemp)
cleanup() {
rm "$index"
rm $index
exit 2
}
trap cleanup INT
trap cleanup 2
# Go back in history while parent commits are available.
echo "Trying to find a commit the patch applies to..."
rev=$(git rev-parse HEAD)
while [ $? = 0 ]
do
GIT_INDEX_FILE=$index git read-tree "$rev"
GIT_INDEX_FILE=$index git read-tree $rev
# Try to apply the patch.
GIT_INDEX_FILE=$index git apply --cached "$1" &>/dev/null
GIT_INDEX_FILE=$index git apply --cached $1 >/dev/null 2>&1
patch_failed=$?
# Do it again, but show the error, if the problem is the patch itself.
if [ $patch_failed = 128 ]
then
GIT_INDEX_FILE=$index git apply --index --check "$1"
GIT_INDEX_FILE=$index git apply --index --check $1
exit $patch_failed
fi
@ -45,19 +45,19 @@ do
then
# Manufacture a commit.
tree=$(GIT_INDEX_FILE=$index git write-tree)
commit=$(git commit-tree "$tree" -p "$rev" -m "$1")
rm "$index"
commit=$(git commit-tree $tree -p $rev -m "$1")
rm $index
echo "Patch applied to $(git rev-parse --short "$rev") as $(git rev-parse --short "$commit")"
echo "Patch applied to $(git rev-parse --short $rev) as $(git rev-parse --short $commit)"
git cherry-pick "$commit"
git cherry-pick $commit
exit $?
fi
rev=$(git rev-parse --verify -q "$rev^")
rev=$(git rev-parse --verify -q $rev^)
done
# No compatible commit found. Restore.
echo "Failed to find a commit the patch applies to."
rm "$index"
rm $index
exit 1

View file

@ -4,17 +4,17 @@ set -e
hook() {
local hook=.git/hooks/$1.sh
# compat without extname
if test ! -f "$hook"; then
if test ! -f $hook; then
hook=.git/hooks/$1
fi
if test -f "$hook"; then
if test -f $hook; then
echo "... $1"
shift
if test -x "$hook"; then
if test -x $hook; then
$hook "$@"
else
. "$hook" "$@"
. $hook "$@"
fi
fi
}
@ -51,12 +51,6 @@ if test $# -gt 0; then
semver=$2
shift
;;
--prefix)
test -z "$2" &&
exit_with_msg "prefix string required for --prefix option"
prefix="$2"
shift
;;
--no-empty-commit) no_empty_commit=true;;
--) shift; hook_args="$hook_args $*"; break;;
*) test -z "$version" && version=$1 ;;
@ -75,7 +69,7 @@ if test $# -gt 0; then
latest_tag=$(git describe --tags "$(git rev-list --tags --max-count=1)")
if [[ ! "$latest_tag" =~ \
^$prefix([^0-9]*)([1-9][0-9]+|[0-9])\.([1-9][0-9]+|[0-9])\.([1-9][0-9]+|[0-9])(.*) ]]; then
^([^0-9]*)([1-9][0-9]+|[0-9])\.([1-9][0-9]+|[0-9])\.([1-9][0-9]+|[0-9])(.*) ]]; then
echo "the latest tag doesn't match semver format requirement" 1>&2
exit 1
fi
@ -92,9 +86,9 @@ if test $# -gt 0; then
(( ++version ))
case "$semver" in
major ) version="$prefix${BASH_REMATCH[1]}$version.0.0${BASH_REMATCH[5]}" ;;
minor ) version="$prefix${BASH_REMATCH[1]}${BASH_REMATCH[2]}.$version.0${BASH_REMATCH[5]}" ;;
patch ) version="$prefix${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}.$version${BASH_REMATCH[5]}" ;;
major ) version="${BASH_REMATCH[1]}$version.0.0${BASH_REMATCH[5]}" ;;
minor ) version="${BASH_REMATCH[1]}${BASH_REMATCH[2]}.$version.0${BASH_REMATCH[5]}" ;;
patch ) version="${BASH_REMATCH[1]}${BASH_REMATCH[2]}.${BASH_REMATCH[3]}.$version${BASH_REMATCH[5]}" ;;
esac
fi
@ -119,7 +113,7 @@ if test $# -gt 0; then
fi
declare -a sign_args
if [ "$sign" = true ]; then
if [ "$sign" == true ]; then
sign_args=("-s")
fi

View file

@ -2,9 +2,9 @@
set -e
# Assert there is at least one branch provided
test -z "$1" && echo "new branch name required." 1>&2 && exit 1
test -z $1 && echo "new branch name required." 1>&2 && exit 1
if [ -z "$2" ]; then
if [ -z $2 ]; then
new_branch="$1"
old_branch="$(git symbolic-ref --short -q HEAD)"
else

View file

@ -1,101 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Usage function
usage() {
cat <<EOF
Usage: git rename-file [OPTIONS] <source> <destination>
Description:
Rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity.
It combines the functionality of the "mv" command and "git mv". This is particularly useful for renaming files or directories
to change only their case, which might not be detected by Git on case-insensitive filesystems.
Options:
-h, --help Show this help message and exit.
Examples:
git rename-file old_filename new_filename
git rename-file old_directory new_directory
EOF
}
# Check for help option
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi
# Check for correct number of arguments
if [ "$#" -ne 2 ]; then
echo "Error: Incorrect number of arguments."
echo ""
usage >&2
exit 1
fi
# Assign variables
SOURCE="$1"
DESTINATION="$2"
TEMP_NAME="${SOURCE}.temp"
# Function to check if a file or directory exists in a case-sensitive manner
check_case_sensitive_exists() {
local path="$1"
local dir
local base
dir=$(dirname "$path")
base=$(basename "$path")
if [ -e "$dir" ]; then
if (cd "$dir" && find . -maxdepth 1 -name "$base" | grep -q "$base"); then
return 0
fi
fi
return 1
}
# Check if source exists and is under version control
if ! check_case_sensitive_exists "$SOURCE"; then
echo "Error: Source '$SOURCE' does not exist."
exit 1
fi
if ! git ls-files --error-unmatch "$SOURCE" > /dev/null 2>&1; then
echo "Error: Source '$SOURCE' is not under version control. If file or directory is new, it must at least be staged."
exit 1
fi
# Check if destination already exists
if check_case_sensitive_exists "$DESTINATION"; then
echo "Error: Destination '$DESTINATION' already exists."
exit 1
fi
# Check if the destination directory exists
DEST_DIR=$(dirname "$DESTINATION")
if ! check_case_sensitive_exists "$DEST_DIR"; then
echo "Error: Destination directory '$DEST_DIR' does not exist."
exit 1
fi
# Create a rollback function
rollback() {
echo "Rolling back changes..."
if [ -e "$TEMP_NAME" ]; then
git mv -f "$TEMP_NAME" "$SOURCE"
fi
}
# Trap errors to trigger rollback
trap 'rollback' ERR
# Move the file to a temporary name within the Git repository
git mv "$SOURCE" "$TEMP_NAME"
# Move the temporary file to the desired destination
git mv "$TEMP_NAME" "$DESTINATION"
echo "Successfully renamed '$SOURCE' to '$DESTINATION'."

View file

@ -5,8 +5,8 @@ set -euo pipefail
old=$1
new=$2
test -z "$old" && echo "old remote name required." 1>&2 && exit 1
test -z "$new" && echo "new remote name required." 1>&2 && exit 1
test -z $old && echo "old remote name required." 1>&2 && exit 1
test -z $new && echo "new remote name required." 1>&2 && exit 1
if ! git config --get "remote.$old.fetch" > /dev/null; then
echo "remote $old doesn't exist"
@ -14,7 +14,7 @@ if ! git config --get "remote.$old.fetch" > /dev/null; then
fi
if git config --get "remote.$new.fetch" > /dev/null; then
git remote remove "$new"
git remote remove $new
fi
git remote rename "$old $new"
git remote rename $old $new
git remote -v

View file

@ -3,10 +3,10 @@
old=$1
new=$2
test -z "$old" && echo "old tag name required." 1>&2 && exit 1
test -z "$new" && echo "new tag name required." 1>&2 && exit 1
test -z $old && echo "old tag name required." 1>&2 && exit 1
test -z $new && echo "new tag name required." 1>&2 && exit 1
git tag "$new" "$old"
git tag -d "$old"
git push origin "$new"
git push origin ":refs/tags/$old"
git tag $new $old
git tag -d $old
git push origin $new
git push origin :refs/tags/$old

View file

@ -1,99 +1,43 @@
#!/usr/bin/env bash
shopt -s extglob
git version
echo "git-extras version ""$(git-extras -v)"
echo "Type 'ls' to ls files below current directory; '!command' to execute any command or just 'subcommand' to execute any git subcommand; 'quit', 'exit', 'q', ^D, or ^C to exit the git repl."
HISTIGNORE=${HISTIGNORE:-+([[:space:]])}
HISTCONTROL=${HISTCONTROL:-ignoredups}
use_local_history=$(git config --get --default 'false' git-extras.repl.use-local-history)
if [[ "$use_local_history" == "true" ]]; then
HISTFILE="$(git rev-parse --show-toplevel)/.git_extras_repl_history"
else
HISTFILE=${XDG_STATE_HOME:-$HOME/.local/state}/git_extras_repl_history
fi
# file doesn't exist, is empty, or contains only whitespace
if [[ ! -f "$HISTFILE" ]] || [[ ! -s "$HISTFILE" ]] || ! grep -q '[^[:space:]]' "$HISTFILE"; then
# `history -r` .... `history -a` are not happy with an empty initial file in bash 3.2.57, which is what MacOS 26 ships with
echo '!echo welcome to git-repl!' >> "$HISTFILE"
fi
history -r
echo "type 'ls' to ls files below current directory, '!command' to execute any command or just 'subcommand' to execute any git subcommand"
while true; do
# Current branch
cur=$(git symbolic-ref HEAD 2> /dev/null | cut -d/ -f3-)
cur=`git symbolic-ref HEAD 2> /dev/null | cut -d/ -f3-`
# Prompt
if test -n "$cur"; then
cur_string=" ($cur)"
prompt="git ($cur)> "
else
cur_string=""
fi
if test -n "$exit_status" && test "$exit_status" -ne 0; then
es_string=$' \e[31m['"$exit_status"$']\e[0m'
else
es_string=""
fi
prompt_character=$(git config --get --default '>' git-extras.repl.prompt-character)
prefix=$(git config --get --default 'git' git-extras.repl.prefix)
show_project_name=$(git config --get --default 'false' git-extras.repl.show-project-name)
if [[ "$show_project_name" == "true" ]]; then
project_name=" $(basename "$(git rev-parse --show-toplevel)" .git)"
else
project_name=""
prompt="git> "
fi
prompt_base="$prefix$project_name$cur_string$es_string$prompt_character"
prompt_base_stripped=$(echo "$prompt_base" | awk '{$1=$1};1')
prompt="$prompt_base_stripped "
# Readline
read -e -r -p "$prompt" cmd
# Use arguments as a command if any are provided.
if [ $# -ne 0 ]; then
cmd=$*
set --
echo "$prompt" "$cmd" # It is as though you had entered a command.
else
# Readline
read -e -r -p "$prompt" cmd
# Check for EOF, and end the program if so (handles ^D).
test $? -ne 0 && break
fi
# EOF
test $? -ne 0 && break
# Add command to history if it is not all whitespace
if [[ ! "$cmd" =~ ^[[:space:]]*$ ]]; then
history -s "$cmd"
fi
# History
history -s "$cmd"
# Built-in commands
case $cmd in
ls) cmd=ls-files;;
"")
on_enter_cmd=$(git config --get --default '' git-extras.repl.on-enter-command)
if test -n "$on_enter_cmd"; then
cmd="$on_enter_cmd"
else
continue
fi
;;
quit|exit|q) break;;
"") continue;;
quit|exit) break;;
esac
history -a
if [[ $cmd == !* ]]; then
# shellcheck disable=SC2086
eval ${cmd:1}
eval ${cmd:1}
elif [[ $cmd == git* ]]; then
# shellcheck disable=SC2086
eval $cmd
else
eval git "$cmd"
fi
exit_status=$?
done
echo

View file

@ -4,14 +4,14 @@ file="$1"
commit="$2"
if [[ -f $file ]]; then
git rm --cached -q -f -- "$file"
if [[ -z $commit ]]; then
git checkout HEAD -- "$file"
git rm --cached -q -f -- $file
if [[ -z $commit ]]; then
git checkout HEAD -- $file
echo "Reset '$1' to HEAD"
else
git checkout "$commit" -- "$file"
git checkout $commit -- $file
echo "Reset '$1' to $commit"
fi
else
echo "File '$1' not found in $PWD"
else
echo "File '$1' not found in `pwd`"
fi

View file

@ -6,13 +6,7 @@ git_root() {
# get the relative path of current path according to root of repo
git_root_relative() {
rel=$(git rev-parse --show-prefix)
if [ -z "$rel" ]; then
# git rev-parse --show-prefix will output empty string when we are in the root dir
echo "."
else
echo "$rel"
fi
git rev-parse --show-prefix
}
if test $# -eq 0; then

View file

@ -18,7 +18,7 @@ function _test_git_scp()
function set_remote()
{
remote=$1
if [ "$(git remote | grep -c -- "^$remote$")" -eq 0 ]
if [ $(git remote | grep -c -- ^$remote$) -eq 0 ]
then
COLOR_RED
echo "Remote $remote does not exist in your git config"
@ -39,9 +39,8 @@ function php_lint()
test ! -f "$i" && continue
case "$i" in
*\.php|*\.phtml)
if ! php -l "$i" > /dev/null; then
error_count[${#error_count[@]}]="$i"
fi
php -l "$i" > /dev/null
[ $? -gt 0 ] && error_count[${#error_count[@]}]="$i"
;;
esac
done
@ -59,17 +58,17 @@ function php_lint()
function _dos2unix()
{
command -v dos2unix > /dev/null && dos2unix "$@"
command -v dos2unix > /dev/null && dos2unix $@
return 0
}
function _sanitize()
{
git config --get-all extras.scp.sanitize | while read -r i
git config --get-all extras.scp.sanitize | while read i
do
case $i in
php_lint) php_lint "$@";; # git config --global --add extras.scp.sanitize php_lint
dos2unix) _dos2unix "$@";; # git config --global --add extras.scp.sanitize dos2unix
php_lint) php_lint $@;; # git config --global --add extras.scp.sanitize php_lint
dos2unix) _dos2unix $@;; # git config --global --add extras.scp.sanitize dos2unix
esac
done
return $?
@ -77,26 +76,14 @@ function _sanitize()
function scp_and_stage
{
local verbose=0 interactive=0 dry_run=0
while :
do
case "$1" in
-v|--verbose) verbose=1; shift;;
-i|--interactive) verbose=1; interactive=1; shift;;
-n|--dry-run) verbose=1; dry_run=1; shift;;
*) break;;
esac
done
set_remote "$1"
set_remote $1
shift
local refhead
refhead="$(git rev-parse --quiet --verify "$1")"
local refhead="$(git rev-parse --quiet --verify $1)"
if [ -n "$refhead" ]
then
shift
[ "$(git branch --contains "$refhead" | grep -c '\*')" -eq 0 ] &&
[ $(git branch --contains "$refhead" | grep -c '\*') -eq 0 ] &&
_error "refhead provided is not part of current branch"
fi
@ -105,117 +92,46 @@ function scp_and_stage
list=$(git ls-files "$@")" "$(git ls-files -o "$@")
elif [ -n "$refhead" ]
then
[ "$verbose" -eq 1 ] && git --no-pager diff --stat "$refhead"
list=$(git diff "$refhead" --name-only)
git diff --stat $refhead
list=$(git diff $refhead --name-only)
else
[ "$verbose" -eq 1 ] && git --no-pager diff
git diff
list=$(git diff --name-only)
fi
deleted=$(for i in $list; do [ -f "$i" ] || echo "$i"; done)
list=$(for i in $list; do [ -f "$i" ] && echo "$i"; done)
if [ "$interactive" -eq 1 ] && [ "$dry_run" -eq 0 ] && { [ -n "$list" ] || [ -n "$deleted" ]; }
then
local reply
read -r -p "Proceed with sync to $remote? [y/N] " reply
case "$reply" in
y|Y|yes|YES) ;;
*) _info "Aborted, nothing synced."; exit 0;;
esac
fi
local status=0
deleted=$(for i in $list; do [ -f $i ] || echo $i; done)
list=$(for i in $list; do [ -f $i ] && echo $i; done)
if [ -n "$list" ]
then
local _TMP=${0///}
# shellcheck disable=SC2086
echo "$list" > "$_TMP"
if [ "$dry_run" -eq 1 ] || _sanitize $list
then
_info "Pushing to $remote ($(git config "remote.$remote.url"))"
if [ "$dry_run" -eq 1 ]
then
rsync -rlDvn --files-from="$_TMP" ./ "$(git config "remote.$remote.url")/"
else
rsync -rlDv --files-from="$_TMP" ./ "$(git config "remote.$remote.url")/" &&
git add --force $list
fi
status=$?
else
status=1
fi
rm "$_TMP"
echo "$list" > $_TMP &&
_sanitize $list &&
_info Pushing to $remote \($(git config remote.$remote.url)\) &&
rsync -rlDv --files-from=$_TMP ./ "$(git config remote.$remote.url)/" &&
git add --force $list &&
rm $_TMP
fi
deleted=$(for i in $deleted; do echo "$(git config "remote.$remote.url" | cut -d: -f2)/$i"; done)
deleted=$(for i in $deleted; do echo $(git config remote.$remote.url | cut -d: -f2)/$i; done)
if [ -n "$deleted" ]
then
COLOR_RED
echo Deleted remote files
if [ "$dry_run" -eq 1 ]
then
echo "$deleted"
else
if ssh "$(git config "remote.$remote.url" | cut -d: -f1)" -t "rm $deleted"
then
echo "$deleted"
else
status=1
fi
fi
COLOR_RESET
fi
return "$status"
[ -n "$deleted" ] &&
COLOR_RED &&
echo Deleted remote files &&
ssh $(git config remote.$remote.url | cut -d: -f1) -t "rm $deleted" &&
echo "$deleted"
COLOR_RESET
}
function reverse_scp()
{
local verbose=0 interactive=0 dry_run=0
while :
do
case "$1" in
-v|--verbose) verbose=1; shift;;
-i|--interactive) verbose=1; interactive=1; shift;;
-n|--dry-run) verbose=1; dry_run=1; shift;;
*) break;;
esac
done
set_remote "$1"
set_remote $1
shift
local _TMP=${0///}
echo "$@" > "$_TMP"
local status=0
if [ "$verbose" -eq 1 ]
then
rsync -rlDvn --files-from="$_TMP" "$(git config "remote.$remote.url")/" ./
status=$?
fi
if [ "$dry_run" -eq 1 ]
then
rm "$_TMP"
return "$status"
fi
if [ "$interactive" -eq 1 ]
then
local reply
read -r -p "Proceed with copy from $remote? [y/N] " reply
case "$reply" in
y|Y|yes|YES) ;;
*) _info "Aborted, nothing copied."; rm "$_TMP"; exit 0;;
esac
fi
rsync -rlDv --files-from="$_TMP" "$(git config "remote.$remote.url")/" ./ &&
rm "$_TMP"
echo $@ > $_TMP &&
rsync -rlDv --files-from=$_TMP "$(git config remote.$remote.url)/" ./ &&
rm $_TMP
}
function _info()
@ -229,18 +145,13 @@ function _usage()
{
echo "Usage:
git scp -h|help|?
git scp [options] <remote> [ref|file..] # scp and stage your files to specified remote
git scp [options] <remote> [<ref>] # show diff relative to <ref> and upload unstaged files to <remote>
git rscp [options] <remote> [<file|directory>] # copy <remote> files to current working directory
OPTIONS:
-v, --verbose print what will be synced before syncing
-i, --interactive prompt for confirmation before syncing (implies --verbose)
-n, --dry-run show what would be synced, change nothing (implies --verbose; no staging, no remote writes/deletes)
git scp <remote> [ref|file..] # scp and stage your files to specified remote
git scp <remote> [<ref>] # show diff relative to <ref> and upload unstaged files to <remote>
git rscp <remote> [<file|directory>] # copy <remote> files to current working directory
"
case $1 in
-v|verbose|--verbose) grep -A100 '^#* OPTIONS #*$' "$0" ;;
-v|verbose|--verbose) grep -A100 '^#* OPTIONS #*$' $0;;
esac
exit
}
@ -250,18 +161,18 @@ function _error()
[ $# -eq 0 ] && _usage && exit 0
echo
echo "ERROR: $*"
echo ERROR: "$@"
echo
exit 1
}
### OPTIONS ###
case $(basename "$0") in
case $(basename $0) in
git-scp)
case $1 in
''|-h|'?'|help|--help) shift; _test_git_scp; _usage "$@";;
*) scp_and_stage "$@";;
''|-h|'?'|help|--help) shift; _test_git_scp; _usage $@;;
*) scp_and_stage $@;;
esac
;;
git-rscp) reverse_scp "$@";;
git-rscp) reverse_scp $@;;
esac

View file

@ -17,7 +17,7 @@ do_commit() {
}
pathspec=
while [ "$1" != "" ]; do
while [ "X$1" != "X" ]; do
case "$1" in
-c|--commit)
if git status --porcelain | grep .; then
@ -33,7 +33,7 @@ actual command:
}
;;
-f|--flags)
if [ "$2" = "" ]; then
if [ "X$2" = "X" ]; then
usage
echo "missing argument for $1"
exit 1
@ -55,11 +55,11 @@ actual command:
exit 1
;;
*)
if [ "$search" = "" ]; then
if [ "X$search" = "X" ]; then
search="$1"
elif [ "$replacement" = "" ]; then
elif [ "X$replacement" = "X" ]; then
replacement="$1"
elif [ "$flags" = "" ]; then
elif [ "X$flags" = "X" ]; then
flags="$1"
else
usage
@ -79,7 +79,7 @@ case "$all" in
escaped="${escaped//[/\\[}"
sep="$(printf '%s' "$ascii" | tr -d "$escaped")"
sep="$(printf %.1s "$sep")"
if [ "$sep" = "" ] ; then
if [ "X$sep" = "X" ] ; then
echo 'could not find an unused character for sed separator character'
exit 1
fi

View file

@ -2,7 +2,7 @@
COMMIT_MESSAGE='Initial commit'
if [ "$1" = "-m" ]; then
if [ "$1" == "-m" ]; then
COMMIT_MESSAGE=$2
shift; shift
fi

View file

@ -1,3 +1,3 @@
#!/usr/bin/env bash
git branch --no-color --merged | grep -v "\*" | grep -v "$(git_extra_default_branch)" | tr -d ' '
git branch --no-color --merged | grep -v "\*" | grep -v $(git_extra_default_branch) | tr -d ' '

View file

@ -1,3 +1,3 @@
#!/usr/bin/env bash
git branch --no-color --no-merged | grep -v "\*" | grep -v "$(git_extra_default_branch)" | tr -d ' '
git branch --no-color --no-merged | grep -v "\*" | grep -v $(git_extra_default_branch) | tr -d ' '

View file

@ -22,7 +22,8 @@ EOF
error() {
if [[ -n "$1" ]]; then
echo "error: $1" >&2
local msg=$( echo "error: $1" )
echo -e "${msg}" >&2
fi
usage
exit 1
@ -33,7 +34,7 @@ stamp() {
local commit_msg=$( git log -1 --pretty=%B )
local stamp_msg
[[ -n "${MSG}" ]] && stamp_msg="${ID} ${MSG}" || stamp_msg="${ID}"
if ${REPLACE}; then
# remove previous stamps with same ID from the commit message
commit_msg=$(
@ -70,9 +71,9 @@ parse_options() {
;;
esac
done
ID="$1"
MSG="${*:2}"
MSG="${@:2}"
}

View file

@ -5,7 +5,7 @@
usage() {
cat <<EOS
Usage:
git standup [-a <author name>] [-w <weekstart-weekend>|-d <days-ago>] [-m <max-dir-depth>] [-D date-format] [-L] [-h] [-f] [-B] [-n <number-of-commits] [-F <gpg|authordate>]
git standup [-a <author name>] [-w <weekstart-weekend>] [-d <days-ago>] [-m <max-dir-depth>] [-g] [-h] [-f] [-B] [-n <number-of-commits]
-a - Specify author to restrict search to, default to current git user.
Use "-a all" if you don't want the restriction.
@ -15,11 +15,10 @@ usage() {
-d - Specify the number of days back to include
-D - Specify the date format for "git log" (default: relative)
-h - Display this help screen
-g - Show if commit is GPG signed (G) or not (N)
-f - Fetch the latest commits beforehand
-B - Display the commits in branch groups
-n - Limit the number of commits displayed per group
-F gpg - Show if commit is GPG signed (G) or not (N)
-F authordate - Print author date instead of commit date
Examples:
git standup -a "John Doe" -w "MON-FRI" -m 3
@ -35,7 +34,7 @@ in_git_repo=$?
# Use colors, but only if connected to a terminal, and that terminal
# supports them.
if command -v tput &>/dev/null; then
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [[ -t 1 ]] && [[ -n "$ncolors" ]] && [[ "$ncolors" -ge 8 ]] ; then
@ -64,11 +63,7 @@ fi
# which may fail on systems lacking tput or terminfo
set -e
RANGE_SPECIFIED=
COMMIT_DATE_FORMAT=%cd
USE_GPG_FORMAT=no
while getopts "hgfF:Bd:a:w:m:D:n:L" opt; do
while getopts "hgfBd:a:w:m:D:n:L" opt; do
case $opt in
h)
usage
@ -82,8 +77,7 @@ while getopts "hgfF:Bd:a:w:m:D:n:L" opt; do
fi
;;
d)
test -n "$RANGE_SPECIFIED" && warn "-d option is conflict with -w"
RANGE_SPECIFIED=yes
test -n "$SINCE" && warn "-d option is conflict with -w"
if [ "$OPTARG" -lt 1 ]; then
>&2 echo "Specify days less than one is invalid"
exit 1
@ -91,11 +85,10 @@ while getopts "hgfF:Bd:a:w:m:D:n:L" opt; do
SINCE="$OPTARG days ago"
;;
w)
if [ -n "$RANGE_SPECIFIED" ]; then
if [ -n "$SINCE" ]; then
warn "-w option is conflict with -d"
continue
fi
RANGE_SPECIFIED=yes
week_range=${OPTARG}
week_start="${week_range%%-*}"
@ -127,8 +120,7 @@ while getopts "hgfF:Bd:a:w:m:D:n:L" opt; do
GIT_DATE_FORMAT=${OPTARG}
;;
g)
warn "-g option is deprecated, use '-F gpg' instead"
USE_GPG_FORMAT=yes
GIT_PRETTY_FORMAT="%C(yellow)gpg: %G?%Creset"
;;
B)
GROUP_BY_BRANCHES=true
@ -136,21 +128,6 @@ while getopts "hgfF:Bd:a:w:m:D:n:L" opt; do
n)
MAX_COMMIT_NUM=${OPTARG}
;;
F)
case $OPTARG in
gpg)
USE_GPG_FORMAT=yes
;;
authordate)
COMMIT_DATE_FORMAT=%ad
;;
*)
warn "Invalid argument for -F: $OPTARG"
usage
exit 1
;;
esac
;;
\?)
usage
exit 1
@ -171,34 +148,13 @@ if [[ $# -gt 0 ]]; then
UNTIL=$3
fi
AUTHOR=${AUTHOR:="$(git config user.name || echo '')"}
if [ -z "${AUTHOR}" ]; then
warn "please configure an author with 'git config user.name' or specify an author via '-a'"
exit 1
fi
AUTHOR=${AUTHOR:="$(git config user.name)"}
SINCE=${SINCE:=yesterday}
UNTIL=${UNTIL:=today}
FETCH_LAST_COMMIT=${FETCH_LAST_COMMIT:=false}
MAXDEPTH=${MAXDEPTH:=2}
GIT_PRETTY_FORMAT="%Cred%h%Creset - %s %Cgreen(${COMMIT_DATE_FORMAT}) %C(bold blue)<%an>%Creset"
GIT_PRETTY_FORMAT="%Cred%h%Creset - %s %Cgreen(%cd) %C(bold blue)<%an>%Creset $GIT_PRETTY_FORMAT"
GIT_DATE_FORMAT=${GIT_DATE_FORMAT:=relative}
if [[ "$USE_GPG_FORMAT" == 'yes' ]]; then
GIT_PRETTY_FORMAT="$GIT_PRETTY_FORMAT %C(yellow)gpg: %G?%Creset"
fi
# Handle config of implicit week
IMPLICIT_WEEK=$(git config --get git-extras.standup.implicit-week || echo '')
if [[ -z "$RANGE_SPECIFIED" ]] && [[ -n "${IMPLICIT_WEEK}" ]]; then
week_start=${IMPLICIT_WEEK%%-*}
week_end=${IMPLICIT_WEEK##*-}
shopt -s nocasematch
if [[ "$week_start" == "$(LC_ALL=C date +%a)" ]]; then
SINCE="last $week_end"
fi
UNTIL=today
else
SINCE=${SINCE:=yesterday}
UNTIL=${UNTIL:=today}
fi
GIT_LOG_COMMAND="git --no-pager log \
--no-merges
@ -210,7 +166,7 @@ GIT_LOG_COMMAND="git --no-pager log \
--color=$COLOR
--pretty=format:'$GIT_PRETTY_FORMAT'
--date='$GIT_DATE_FORMAT'"
if [[ -n "$MAX_COMMIT_NUM" ]]; then
if [[ ! -z "$MAX_COMMIT_NUM" ]]; then
GIT_LOG_COMMAND="$GIT_LOG_COMMAND --max-count=$MAX_COMMIT_NUM"
fi
@ -221,13 +177,13 @@ git_output() {
for branch in $branches; do
# shellcheck disable=SC2086
if output=$(eval $GIT_LOG_COMMAND "$branch"); then
if [[ -n "$output" ]] ; then
if [[ ! -z "$output" ]] ; then
echo "${GREEN}${branch}${NORMAL}"
echo "$output"
echo ""
fi
fi
# TODO optimize:return if the latest commit of a branch is earlier than the 'since' day
# TODO optimize:return if the latest commit of a branch is eariler than the 'since' day
done
else
# shellcheck disable=SC2086
@ -240,7 +196,6 @@ if [[ $in_git_repo != 0 ]]; then
## Set delimiter to newline for the loop
IFS=$'\n'
## Recursively search for git repositories
# shellcheck disable=SC2086
PROJECT_DIRS=$(find $INCLUDE_LINKS . -maxdepth "$MAXDEPTH" -mindepth 0 -name .git)
# Fetch the latest commits, if required
@ -270,7 +225,7 @@ if [[ $in_git_repo != 0 ]]; then
if [[ -d ".git" || -f ".git" ]] ; then
if GITOUT=$(git_output); then
## Only output if there is some activities
if [[ -n "$GITOUT" ]] ; then
if [[ ! -z "$GITOUT" ]] ; then
echo "${BOLD}${UNDERLINE}${YELLOW}$(basename "$DIR")${NORMAL}"
echo "$GITOUT"
echo ""
@ -288,7 +243,7 @@ else
fi
if GITOUT=$(git_output); then
if [[ -n "$GITOUT" ]] ; then
if [[ ! -z "$GITOUT" ]] ; then
echo "$GITOUT"
else
if [[ $AUTHOR = '.*' ]] ; then

View file

@ -3,29 +3,16 @@
cd "$(git root)" || { echo "Can't cd to top level directory";exit 1; }
PROJECT_FULL_PATH=
SUMMARY_BY_LINE=
DEDUP_BY_EMAIL=
MERGES_ARG=
OUTPUT_STYLE=
for arg in "$@"; do
case "$arg" in
--full-path)
PROJECT_FULL_PATH=1
;;
--line)
SUMMARY_BY_LINE=1
;;
--dedup-by-email)
DEDUP_BY_EMAIL=1
;;
--no-merges)
MERGES_ARG="--no-merges"
;;
--output-style)
OUTPUT_STYLE="$2"
shift
;;
-*)
>&2 echo "unknown argument $arg found"
exit 1
@ -44,38 +31,27 @@ if [ -n "$DEDUP_BY_EMAIL" ] && [ -n "$SUMMARY_BY_LINE" ]; then
exit 1
fi
if [ -n "$MERGES_ARG" ] && [ -n "$SUMMARY_BY_LINE" ]; then
>&2 echo "--no-merges used with --line is not supported"
exit 1
fi
commit="HEAD"
if [ -n "$SUMMARY_BY_LINE" ]; then
paths=( "$@" )
else
[ $# -ne 0 ] && commit=$*
fi
if [[ -n "$PROJECT_FULL_PATH" ]]; then
project=${PWD/${HOME}/\~}
else
project=${PWD##*/}
fi
commit=""
test $# -ne 0 && commit=$*
project=${PWD##*/}
#
# get date for the given <commit>
#
commit_date() {
date() {
# the $1 can be empty
# shellcheck disable=SC2086
git log $MERGES_ARG --pretty='format: %ai' "$1" | cut -d ' ' -f 2
git log --pretty='format: %ai' $1 | cut -d ' ' -f 2
}
#
# get active days for the given <commit>
#
active_days() {
commit_date "$1" | sort -r | uniq | awk '
# shellcheck disable=SC2086
date $1 | sort -r | uniq | awk '
{ sum += 1 }
END { print sum }
'
@ -84,14 +60,16 @@ active_days() {
#
# get the commit total
#
commit_count() {
# shellcheck disable=SC2086
git rev-list $MERGES_ARG --count "$commit"
git log --oneline $commit | wc -l | tr -d ' '
}
#
# total file count
#
file_count() {
git ls-files | wc -l | tr -d ' '
}
@ -99,20 +77,20 @@ file_count() {
#
# remove duplicate authors who belong to the same email address
#
dedup_by_email() {
# in:
# 27 luo zexuan <LuoZexuan@xxx.com>
# 27 luo zexuan <luozexuan@xxx.com>
# 7 罗泽轩 <luozexuan@xxx.com>
# out:
# 34 luo zexuan
LC_ALL=C awk '
{
sum += $1
last_field = tolower($NF)
if (last_field in emails) {
emails[last_field] += $1
if ($NF in emails) {
emails[$NF] += $1
} else {
email = last_field
email = $NF
emails[email] = $1
# set commits/email to empty
$1=$NF=""
@ -139,6 +117,7 @@ dedup_by_email() {
#
# list authors
#
format_authors() {
# a rare unicode character is used as separator to avoid conflicting with
# author name. However, Linux column utility will escape tab if separator
@ -156,17 +135,11 @@ format_authors() {
#
# fetch repository age from oldest commit
#
repository_age() {
git log --reverse --pretty=oneline --format="%ar" | head -n 1 | LC_ALL=C sed 's/ago//'
}
#
# fetch repository age of the latest commit
#
last_active() {
git log --pretty=oneline --format="%ar" -n 1
}
#
# list the last modified author for each line
#
@ -174,86 +147,51 @@ single_file() {
while read -r data
do
if [[ $(file "$data") = *text* ]]; then
git blame --line-porcelain "$data" 2>/dev/null | grep "^author " | LC_ALL=C sed -n 's/^author //p';
git blame --line-porcelain "$data" 2>/dev/null | grep "^author\ " | LC_ALL=C sed -n 's/^author //p';
fi
done
}
current_branch_name() {
git rev-parse --abbrev-ref HEAD
}
#
# list the author for all file
#
lines() {
git ls-files -- "$@" | single_file
git ls-files | single_file
}
#
# get the number of the lines
#
line_count() {
lines "$@" | wc -l
lines | wc -l
}
uncommitted_changes_count() {
git status --porcelain | wc -l
}
# summary
COLUMN_CMD_DELIMTER="¬" # Hopefully, this symbol is not used in branch names... I use it as a separator for columns
SP="$COLUMN_CMD_DELIMTER|"
print_summary_by_line() {
if [ "$OUTPUT_STYLE" = "tabular" ]; then
tabular_headers="# Repo $SP Lines"
echo -e "$tabular_headers\n$project $SP $(line_count "${paths[@]}")" | column -t -s "$COLUMN_CMD_DELIMTER"
elif [ "$OUTPUT_STYLE" = "oneline" ]; then
echo "$project / lines: $(line_count "${paths[@]}")"
elif [ -n "$SUMMARY_BY_LINE" ]; then
echo
echo " project : $project"
echo " lines : $(line_count "${paths[@]}")"
echo " authors :"
lines "${paths[@]}" | sort | uniq -c | sort -rn | format_authors
fi
}
print_summary() {
if [ "$OUTPUT_STYLE" = "tabular" ]; then
tabular_headers="# Repo $SP Age $SP Last active $SP Active on $SP Commits $SP Uncommitted $SP Branch"
echo -e "$tabular_headers\n$project $SP $(repository_age) $SP $(last_active) $SP $(active_days "$commit") days $SP $(commit_count "$commit") $SP $(uncommitted_changes_count) $SP $(current_branch_name)" | column -t -s "$COLUMN_CMD_DELIMTER"
elif [ "$OUTPUT_STYLE" = "oneline" ]; then
echo "$project / age: $(repository_age) / last active: $(last_active) / active on $(active_days "$commit") days / commits: $(commit_count "$commit") / uncommitted: $(uncommitted_changes_count) / branch: $(current_branch_name)"
else
echo
echo " project : $project"
echo " repo age : $(repository_age)"
echo " branch: : $(current_branch_name)"
echo " last active : $(last_active)"
echo " active on : $(active_days "$commit") days"
echo " commits : $(commit_count "$commit")"
# The file count doesn't support passing a git ref so ignore it if a ref is given
if [ "$commit" = "HEAD" ]; then
echo " files : $(file_count)"
fi
echo " uncommitted : $(uncommitted_changes_count)"
echo " authors : "
if [ -n "$DEDUP_BY_EMAIL" ]; then
# the $commit can be empty
# shellcheck disable=SC2086
git shortlog $MERGES_ARG -n -s -e "$commit" | dedup_by_email | format_authors
else
# shellcheck disable=SC2086
git shortlog $MERGES_ARG -n -s "$commit" | format_authors
fi
fi
}
echo
echo " project : $project"
if [ -n "$SUMMARY_BY_LINE" ]; then
print_summary_by_line
echo " lines : $(line_count)"
echo " authors :"
lines | sort | uniq -c | sort -rn | format_authors
else
print_summary
# shellcheck disable=SC2046
echo " repo age :" $(repository_age)
# shellcheck disable=SC2086
echo " active :" "$(active_days $commit)" days
echo " commits :" "$(commit_count)"
if test "$commit" = ""; then
echo " files :" "$(file_count)"
fi
echo " authors : "
if [ -n "$DEDUP_BY_EMAIL" ]; then
# the $commit can be empty
# shellcheck disable=SC2086
git shortlog -n -s -e $commit | dedup_by_email | format_authors
else
# shellcheck disable=SC2086
git shortlog -n -s $commit | format_authors
fi
fi

View file

@ -8,7 +8,6 @@ Usage:
${command} [<remote> <branch>]
${command} -h | --help
${command} -s | --soft
${command} -f | --force
Sync local branch with <remote>/<branch>.
When <remote> and <branch> are not specified on the command line, upstream of local branch will be used by default.
@ -23,9 +22,6 @@ Examples:
Sync without cleaning untracked files:
${command} -s
Sync without interaction:
${command} -f
EOS
}
@ -40,9 +36,6 @@ function main()
-s | --soft)
local soft="true"
;;
-f | --force)
local force="YES"
;;
* )
if [ "${remote}" = "" ]; then
local remote="$1"
@ -59,14 +52,14 @@ function main()
done
local remote_branch
if [ -z "${remote}" ]; then
if ! remote_branch="$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null)"; then
if [ "${remote}" = "" ]; then
if ! remote_branch="$(git rev-parse --abbrev-ref --symbolic-full-name @{u} 2>/dev/null)"; then
echo "There is no upstream information of local branch."
exit 1
fi
local branch="$(git rev-parse --abbrev-ref --symbolic-full-name @)"
local remote=$(git config "branch.${branch}.remote")
elif [ -z "${branch}" ]; then
elif [ "${branch}" = "" ]; then
echo -e "Error: too few arguments.\n"
_usage
exit 1
@ -74,16 +67,10 @@ function main()
remote_branch="${remote}/${branch}"
fi
if [ "${force}" != "YES" ]; then
if [ "${soft}" = "true" ]; then
echo -n "Are you sure you want to sync with '${remote_branch}'? [y/N]: "
else
echo -n "Are you sure you want to clean all changes & sync with '${remote_branch}'? [y/N]: "
fi
local force
read -r force
fi
case "${force}" in
echo -n "Are you sure you want to clean all changes & sync with '${remote_branch}'? [y/N]: "
local res
read res
case "${res}" in
"Y" | "y" | "yes" | "Yes" | "YES" )
if [ "${soft}" = "true" ]; then
git fetch "${remote}" "${branch}" && git reset --hard "${remote_branch}"

View file

@ -7,7 +7,7 @@ USAGE(){
test $# -lt 1 && USAGE
for filename in "$@"; do
for filename in $@; do
touch "$filename" \
&& git add "$filename"
done

View file

@ -2,7 +2,7 @@
cstr="commits"
ccnt=$(git rev-list --count HEAD)
if [ "$ccnt" -eq 1 ]; then cstr="commit"; fi
if [ $ccnt -eq 1 ]; then cstr="commit"; fi
parm3=""
function _undo()
@ -11,14 +11,14 @@ function _undo()
undo_cnt=${2:-1}
reset=${3:-""}
if [ "$undo_cnt" -gt "$ccnt" ]; then
if [ $undo_cnt -gt $ccnt ]; then
echo "Only $ccnt $cstr, cannot undo $undo_cnt"
elif [ "$type" = "hard" ] && [ "$ccnt" -eq "$undo_cnt" ]; then
elif [ "$type" = "hard" ] && [ $ccnt -eq $undo_cnt ]; then
echo "Cannot hard undo all commits"
elif [ "$type" = "soft" ] && [ "$ccnt" -eq 1 ]; then
elif [ "$type" = "soft" ] && [ $ccnt -eq 1 ]; then
git update-ref -d HEAD
else
git reset "--$type" "HEAD~$undo_cnt"
git reset --$type HEAD~$undo_cnt
fi
if [ "$reset" != "" ]; then git reset; fi
}
@ -69,4 +69,4 @@ if [[ ! $parm2 =~ ^[1-9][0-9]*$ ]]; then
exit 1
fi
_undo "$parm1" "$parm2" "$parm3"
_undo $parm1 $parm2 $parm3

View file

@ -1,5 +1,5 @@
#!/usr/bin/env bash
filename="$1"
test -z "$filename" && echo "filename required." 1>&2 && exit 1
git update-index --no-skip-worktree "$filename"
filename=$1
test -z $filename && echo "filename required." 1>&2 && exit 1
git update-index --no-skip-worktree $filename

View file

@ -1,14 +0,0 @@
#!/usr/bin/env bash
# Based on scripts from git-utils:
# * https://github.com/ddollar/git-utils/blob/master/git-unwip
# Check if the last commit is a 'WIP' commit
LAST_COMMIT=`git log -1 --pretty=%B | tr -d '[:space:]'`
if [ 'WIP' != $LAST_COMMIT ]; then
echo 'Last commit is not a WIP commit, so it will not be unWIP-ed.'
exit 1
fi
git undo --soft

View file

@ -2,130 +2,29 @@
#
# Change files modification time to their last commit date
#
# Bash unofficial strict mode
set -euo pipefail
IFS=$'\n\t'
if [[ "${1:-}" == "--newer" ]]; then
op=le
if [ "$1" = --touch ]; then
# Internal use option only just to parallelize things.
shift
for f; do
iso_t=$(git --no-pager log --no-renames --pretty=format:%cI -1 @ -- "$f" 2>/dev/null)
if [ -n "$iso_t" ]; then
bsd=$(date -j > /dev/null 2>&1 && echo 'true')
if [ "$bsd" == "true" ]; then
t=$(date -j -f %Y-%m-%dT%H:%M:%S "$iso_t" +%Y%m%d%H%M.%S)
else
t=$(date -d"$iso_t" +%Y%m%d%H%M.%S)
fi
echo "+ touch -t $t $f" >&2
touch -t "$t" "$f"
fi
done
else
op=eq
opt_r=$(xargs -r false < /dev/null > /dev/null 2>&1 && echo '-r')
# `-n` should be limited or parallelization will not give effect,
# because all args will go into single worker.
NPROC=$(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || getconf _NPROCESSORS_ONLN 2>/dev/null)
# shellcheck disable=SC2086
git ls-tree -z -r -t --name-only @ \
| xargs -0 -P${NPROC:-1} -n${NPROC:-1} $opt_r git utimes --touch
fi
# BSD systems
if date -j &>/dev/null; then
stat_flags="-f %m"
date_flags="-r"
else
# Non-BSD systems
stat_flags="-c %Y"
date_flags="-d@"
fi
bash_opts=()
if bash --help 2>&1 | grep -q -- '--noprofile'; then
bash_opts+=(--noprofile)
fi
if bash --help 2>&1 | grep -q -- '--norc'; then
bash_opts+=(--norc)
fi
status_opts=(--porcelain --short)
# %ct: committer date, UNIX timestamp / %at: author date, UNIX timestamp
log_opts=(--format='%ct')
if git status --help 2>&1 | grep -q -- "--no-renames"; then
status_opts+=(--no-renames)
log_opts+=(--no-renames)
fi
if git status --help 2>&1 | grep -q -- "--untracked-files"; then
status_opts+=(--untracked-files=no)
fi
if git status --help 2>&1 | grep -q -- "--ignored"; then
status_opts+=(--ignored=no)
fi
prefix="$(git rev-parse --show-prefix) "
strip="${#prefix}"
tmpfile=$(mktemp)
# shellcheck disable=SC2064
trap "rm -f '${tmpfile}'" 0
awk_flags=(
-F'\t'
-v date_flags="${date_flags}"
-v op="${op}"
-v stat_flags="${stat_flags}"
-v strip="${strip}"
-v tmpfile="${tmpfile}"
)
# sanity check, not required:
if awk --help 2>&1 | grep -q -- '--posix'; then
awk_flags+=(--posix)
fi
read -r -d '' awk_script <<"EOF" || true
BEGIN {
seen[""]=1
print "#!/usr/bin/env bash"
print "set +e"
print "t() {"
print " test -e \"$2\" || return 0"
printf(" test \"$(stat %s \"$2\" 2>/dev/null)\" -%s \"$1\" && return 0\n", stat_flags, op)
if (date_flags == "-d@") {
print " echo \"+ touch -h -d@$1 $2\""
print " touch -h -d@$1 \"$2\""
} else {
print " t=$(date -r$1 \"+%Y%m%d%H%M.%S\")"
print " echo \"+ touch -h -t $t $2\""
print " touch -h -t $t \"$2\""
}
print "}"
}
FILENAME==tmpfile {
skip[$1]=1
next
}
# skip blank lines
!/^$/ {
# skip deletes
if (substr($1, length($1), 1) ~ /D/) {
next
}
if (NF == 1) {
ct=$1
next
}
$2 = substr($2, strip, length($2)- strip + 1)
if ($2 in seen) {
next
}
if ($2 in skip) {
next
}
seen[$2]=1
# remove enclosing double quotes that git adds:
if (substr($2, 1, 1) == "\"" && substr($2, length($2), 1) == "\"") {
$2 = substr($2, 2, length($2) - 2)
# unescape remaining double quotes
gsub(/\\"/, "\"", $2)
# unescape escaped backslashes
gsub(/\\\\/, "\\", $2)
}
# escape apostrophes: ' => '\''
gsub(/'/, "'\\''", $2)
printf("t %s '%s'\n", ct, $2)
}
EOF
# prefix is stripped:
git --no-pager status "${status_opts[@]}" . \
| cut -c 4- >"${tmpfile}"
# prefix is not stripped:
git --no-pager log --raw --no-merges "${log_opts[@]}" . \
| awk "${awk_flags[@]}" "${awk_script}" "${tmpfile}" - \
| BASH_ENV='' bash "${bash_opts[@]}" -

View file

@ -1,8 +0,0 @@
#!/usr/bin/env bash
# Based on scripts from git-utils:
# * https://github.com/ddollar/git-utils/blob/master/git-wip
# * https://github.com/ddollar/git-utils/blob/master/git-addremove
git add --all
git commit --all --message="WIP"

View file

@ -3,10 +3,10 @@ index e49cd24..4ae28b5 100755
--- a/bin/git-extras
+++ b/bin/git-extras
@@ -4,13 +4,12 @@ VERSION="4.3.0"
INSTALL_SCRIPT="https://raw.githubusercontent.com/tj/git-extras/main/install.sh"
INSTALL_SCRIPT="https://raw.githubusercontent.com/tj/git-extras/master/install.sh"
update() {
- local bin="$(command -v git-extras)"
- local bin="$(which git-extras)"
- local prefix=${bin%/*/*}
- local orig=$PWD
-

View file

@ -6,5 +6,5 @@ err() {
}
if ! command -v column >/dev/null 2>&1; then
err "Need to install dependency 'column' before installation (can be found in bsdmainutils)"
err "Need to install dependency 'column' before installation"
fi

View file

@ -6,7 +6,7 @@ err() {
}
make_doc() {
echo "touch man/git-$1.md && make man/git-$1.{1,html}"
echo "'touch man/git-$1.md && make man/git-$1.{1,html}'"
}
check_bash_script() {
@ -25,7 +25,7 @@ check_bash_script() {
check_git_extras_cmd_list() {
local whitelist=('extras')
for cmd in "${whitelist[@]}"; do
for cmd in ${whitelist[*]}; do
test "$1" == "$cmd" && return
done
@ -47,11 +47,6 @@ check_documentation() {
err "Create man/$cmd.1 and man/$cmd.html via $(make_doc "$1")"
fi
if [ "man/$cmd.md" -nt "man/$cmd.1" ] || [ "man/$cmd.md" -nt "man/$cmd.html" ]
then
err "man/$cmd.md, man/$cmd.1, and man/$cmd.html all exist, but man/$cmd.md is newer. You should rm man/$cmd.{1,html} && $(make_doc "$1")"
fi
check_git_extras_cmd_list "$@"
check_man_page_index "$@"
}
@ -59,7 +54,7 @@ check_documentation() {
check_Commands_page() {
# These are special cases. All listed together, so we ignore them
local whitelist=('bug' 'chore' 'feature' 'refactor')
for cmd in "${whitelist[@]}"; do
for cmd in ${whitelist[*]}; do
test "$1" == "$cmd" && return
done
@ -82,9 +77,12 @@ check() {
check_completion "$1"
}
test $# == 0 && set -- $(find bin | cut -b 5- | xargs)
usage() {
echo >&2 "Usage: ./check_integrity.sh <command-name> [<command-name2> ...]"
exit 0
}
./bin/git-utimes --newer
test $# == 0 && usage
for name in "$@"; do
name=${name#git-}

View file

@ -1,29 +1,5 @@
# shellcheck shell=bash
# bash completion support for git-extras.
__gitex_heads_unique() {
local branch specified=("${COMP_WORDS[@]:2}")
for branch in $(__git_heads); do
[[ " ${specified[*]} " == *" $branch "* ]] || printf '%s\n' "$branch"
done
}
_git_authors(){
__gitcomp "-l --list --no-email"
}
_git_browse(){
__git_complete_remote_or_refspec
}
_git_browse_ci(){
__git_complete_remote_or_refspec
}
_git_brv(){
__gitcomp "-r --reverse"
}
_git_changelog(){
local s_opts=( '-a' '-l' '-t' '-f' '-s' '-n' '-p' '-x' '-h' '?' )
local l_opts=(
@ -45,29 +21,8 @@ _git_changelog(){
__gitcomp "$merged_opts_str"
}
_git_coauthor(){
local oldIfs=$IFS
IFS=$'\n'
local cur="${COMP_WORDS[COMP_CWORD]}"
local selection=
if ((COMP_CWORD == 2)); then
for line in $(git authors --list); do
selection+="${line% *}"$'\n'
done
elif ((COMP_CWORD == 3)); then
local chosen_name="${COMP_WORDS[COMP_CWORD-1]}"
for line in $(git authors --list); do
if [ "$chosen_name" = "${line% *}" ]; then
local email=${line#*<}
email=${email%>*}
selection+="$email"$'\n'
fi
done
fi
compopt +o default
compopt -o filenames
COMPREPLY=($(compgen -W "$selection" -- "$cur"))
IFS=$oldIfs
_git_authors(){
__gitcomp "-l --list --no-email"
}
_git_contrib(){
@ -82,10 +37,6 @@ _git_contrib(){
COMPREPLY=($(compgen -W "$all" -- "$cur"))
}
_git_commits_since(){
__gitcomp "-r --ref"
}
_git_count(){
__gitcomp "--all"
}
@ -95,10 +46,6 @@ __git_cp(){
}
_git_delete_branch(){
__gitcomp "$(__gitex_heads_unique)"
}
_git_delete_squashed_branches(){
__gitcomp "$(__git_heads)"
}
@ -115,7 +62,6 @@ _git_effort(){
case "$cur" in
--*)
# shellcheck disable=SC2154
__gitcomp "
--above
$__git_log_common_options
@ -131,7 +77,7 @@ _git_extras(){
}
__git_extras_workflow(){
__gitcomp "$(__git_heads | grep -- "^$1/" | sed s/^"$1"\\///g) finish"
__gitcomp "$(__git_heads | grep -- ^$1/ | sed s/^$1\\///g) finish"
}
_git_feature(){
@ -145,20 +91,16 @@ _git_graft(){
_git_ignore(){
case "$cur" in
--*)
__gitcomp "--global --local --private --edit --remove"
__gitcomp "--global --local --private"
return
;;
-*)
__gitcomp "--global --local --private --edit --remove -g -l -p -e -r"
__gitcomp "--global --local --private -g -l -p"
return
;;
esac
}
_git_info(){
__gitcomp "--color -c --no-config"
}
_git_missing(){
# Suggest all known refs
__gitcomp "$(git for-each-ref --format='%(refname:short)')"
@ -181,29 +123,15 @@ _git_reauthor(){
__gitcomp "${comp}"
}
__git_extras_rename(){
if ((COMP_CWORD == 2 || COMP_CWORD == 3)); then
__gitcomp "$1"
fi
}
_git_rename_branch(){
__git_extras_rename "$(__git_heads)"
}
_git_rename_remote(){
__git_extras_rename "$(__git_remotes)"
}
_git_rename_tag(){
__git_extras_rename "$(__git_tags)"
}
_git_rscp(){
_git_scp(){
__git_complete_remote_or_refspec
}
_git_scp(){
_git_stamp(){
__gitcomp '--replace -r'
}
_git_rscp(){
__git_complete_remote_or_refspec
}
@ -211,10 +139,14 @@ _git_squash(){
__gitcomp "$(__git_heads)"
}
_git_stamp(){
__gitcomp '--replace -r'
}
_git_undo(){
__gitcomp "--hard --soft -h -s"
}
_git_info(){
__gitcomp "--color -c --no-config"
}
_git_browse(){
__git_complete_remote_or_refspec
}

View file

@ -51,7 +51,7 @@ __gitex_remote_names() {
local expl
declare -a remote_names
remote_names=(${(f)"$(_call_program remotes git remote 2>/dev/null)"})
__gitex_command_successful || return
__git_command_successful || return
_wanted remote-names expl remote-name compadd $* - $remote_names
}
@ -59,7 +59,7 @@ __gitex_tag_names() {
local expl
declare -a tag_names
tag_names=(${${(f)"$(_call_program tags git for-each-ref --format='"%(refname)"' refs/tags 2>/dev/null)"}#refs/tags/})
__gitex_command_successful || return
__git_command_successful || return
_wanted tag-names expl tag-name compadd $* - $tag_names
}
@ -68,24 +68,15 @@ __gitex_branch_names() {
local expl
declare -a branch_names
branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/})
__gitex_command_successful || return
__git_command_successful || return
_wanted branch-names expl branch-name compadd $* - $branch_names
}
__gitex_branch_names_unique() {
local expl
declare -a branch_names already_specified
branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/})
__gitex_command_successful || return
already_specified=(${words[2,-1]})
_wanted branch-names expl branch-name compadd -F already_specified $* - $branch_names
}
__gitex_specific_branch_names() {
local expl
declare -a branch_names
branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads/"$1" 2>/dev/null)"}#refs/heads/$1/})
__gitex_command_successful || return
__git_command_successful || return
_wanted branch-names expl branch-name compadd - $branch_names
}
@ -97,31 +88,16 @@ __gitex_submodule_names() {
local expl
declare -a submodule_names
submodule_names=(${(f)"$(_call_program branchrefs git submodule status | awk '{print $2}')"}) # '
__gitex_command_successful || return
__git_command_successful || return
_wanted submodule-names expl submodule-name compadd $* - $submodule_names
}
__gitex_workspace_names() {
local expl
declare -a workspace_names
workspace_names=($(git bulk --listall | awk '{print $1}' | cut -d "." -f 2))
__gitex_command_successful || return
_wanted workspace-names expl workspace-names compadd $* - $workspace_names
}
__gitex_author_names() {
local expl
declare -a author_names
author_names=(${(f)"$(_call_program branchrefs git log --format='%aN' | sort -u)"})
__gitex_command_successful || return
_wanted author-names expl author-name compadd $* - $author_names
}
__gitex_author_emails() {
local expl
declare -a author_names
author_names=(${(f)"$(_call_program branchrefs git log --format='%aE' | sort -u)"})
__gitex_command_successful || return
__git_command_successful || return
_wanted author-names expl author-name compadd $* - $author_names
}
@ -133,47 +109,15 @@ _git-authors() {
'--no-email[without email]' \
}
_git-brv() {
_arguments \
'(-r --reverse)'{-r,--reverse}'[reverse order]'
}
_git-bulk() {
_arguments \
'-a[Run a git command on all workspaces and their repositories.]' \
'-g[Ask the user for confirmation on every execution (guarded mode).]' \
'-w[Run the git command on the specified workspace.]:workspace-name:__gitex_workspace_names' \
'-q[Suppress bulk output about current execution (quiet mode).]' \
'--no-follow-symlinks[Do not traverse symbolic links when searching for git repositories.]' \
'--no-follow-hidden[Do not traverse hidden directories when searching for git repositories.]' \
'--addworkspace[Register a workspace for bulk operations.]' \
'--removeworkspace[Remove the specified workspace.]:workspace-name:__gitex_workspace_names' \
'--addcurrent[Adds the current directory as workspace to git bulk operations]' \
'--purge[Removes all defined repository locations.]' \
'--listall[List all registered repositories.]' \
'--help[Show the help.]'
}
_git-changelog() {
_arguments \
'(-l --list)'{-l,--list}'[list commits]' \
}
_git-clear() {
_arguments \
'(-f --force)'{-f,--force}'[force clear]' \
'(-h --help)'{-h,--help}'[help message]' \
}
_git-coauthor() {
_arguments \
':co-author[co-author to add]:__gitex_author_names' \
':co-author-email[email address of co-author to add]:__gitex_author_emails'
}
_git-commits-since() {
_arguments \
'(-r --ref)'{-r,--ref}'[show commits since ref]'
':co-author[co-author to add]' \
':co-author-email[email address of co-author to add]'
}
_git-contrib() {
@ -210,15 +154,6 @@ _git-create-branch() {
}
_git-delete-branch() {
__gitex_branch_names_unique
}
_git-delete-gone-branches() {
_arguments \
'(-n --dry-run)'{-n,--dry-run}'[show branches that would be deleted without deleting]'
}
_git-delete-squashed-branches() {
_arguments \
':branch-name:__gitex_branch_names'
}
@ -317,12 +252,9 @@ _git-guilt() {
_git-ignore() {
_arguments -C \
'(--local -l)'{--local,-l}'[set context to local gitignore]' \
'(--global -g)'{--global,-g}'[set context to global gitignore]' \
'(--private -p)'{--private,-p}'[set context to private gitignore]' \
'(--edit -e)'{--edit,-e}'[set action to edit]' \
'(--remove -r)'{--remove,-r}'[set action to remove]' \
'*:filename:_files'
'(--local -l)'{--local,-l}'[show local gitignore]' \
'(--global -g)'{--global,-g}'[show global gitignore]' \
'(--private -p)'{--private,-p}'[show repo gitignore]'
}
@ -354,19 +286,10 @@ _git-release() {
'-s[Create a signed and annotated tag.]' \
'-u[Create a tag, annotated and signed with the given key.]' \
'--semver[If the latest tag in your repo matches the semver format requirement, you could increase part of it as the new release tag.]' \
'--prefix[Add a prefix string to semver to allow more complex tags.]' \
'--no-empty-commit[Avoid creating empty commit if nothing could be committed.]' \
'--[The arguments listed after "--" separator will be passed to pre/post-release hook.]'
}
_git-rename-file() {
_arguments -C \
'-h[show usage information]' \
'--help[show usage information]' \
'1:source:__git_files' \
'2:destination:__git_files'
}
_git-squash() {
_arguments '--squash-msg[commit with the squashed commit messages]'
_arguments \
@ -392,10 +315,8 @@ _git-standup() {
}
_git-summary() {
_arguments '--full-path[show repository full path]'
_arguments '--line[summarize with lines rather than commits]'
_arguments '--dedup-by-email[remove duplicate users by the email address]'
_arguments '--no-merges[exclude merge commits]'
__gitex_commits
}
@ -409,11 +330,9 @@ zstyle -g existing_user_commands ':completion:*:*:git:*' user-commands
zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
alias:'define, search and show aliases' \
abort:'abort current revert, merge, rebase, or cherry-pick process' \
archive-file:'export the current head of the git repository to an archive' \
authors:'generate authors report' \
browse:'open repo website in browser' \
browse-ci:'open repo CI page in browser' \
bug:'create bug branch' \
bulk:'run bulk commands' \
brv:'list branches sorted by their last commit date'\
@ -423,14 +342,11 @@ zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
clear:'rigorously clean up a repository' \
coauthor:'add a co-author to the last commit' \
commits-since:'show commit logs since some date' \
continue:'continue current revert, merge, rebase, or cherry-pick process' \
contrib:'show user contributions' \
count:'show commit count' \
create-branch:'create branches' \
delete-branch:'delete branches' \
delete-gone-branches:'delete branches whose remote is gone' \
delete-merged-branches:'delete merged branches' \
delete-squashed-branches:'delete squashed branches' \
delete-submodule:'delete submodules' \
delete-tag:'delete tags' \
delta:'lists changed files' \
@ -438,19 +354,17 @@ zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
extras:'awesome git utilities' \
feature:'create/merge feature branch' \
force-clone:'overwrite local repositories with clone' \
fork:'fork a repo on GitHub' \
fork:'fork a repo on github' \
fresh-branch:'create fresh branches' \
get:'clone a repository in a directory' \
gh-pages:'create the GitHub pages branch' \
gh-pages:'create the github pages branch' \
graft:'merge and destroy a given branch' \
guilt:'calculate change between two revisions' \
ignore-io:'get sample gitignore file' \
ignore:'Modify or display .gitignore files' \
ignore:'add .gitignore patterns' \
info:'returns information on current repository' \
local-commits:'list local commits' \
lock:'lock a file excluded from version control' \
locked:'ls files that have been locked' \
magic:'commits everything with a generated message' \
merge-into:'merge one branch into another' \
merge-repo:'merge two repo histories' \
missing:'show commits missing from another branch' \
@ -465,7 +379,6 @@ zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
refactor:'create refactor branch' \
release:'commit, tag and push changes to the repository' \
rename-branch:'rename a branch' \
rename-file:'rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity' \
rename-tag:'rename a tag' \
rename-remote:'rename a remote' \
repl:'git read-eval-print-loop' \
@ -485,6 +398,4 @@ zstyle ':completion:*:*:git:*' user-commands $existing_user_commands \
touch:'touch and add file to the index' \
undo:'remove latest commits' \
unlock:'unlock a file excluded from version control' \
utimes:'change files modification time to their last commit date' \
unwip:'undo a WIP commit' \
wip:'create a WIP commit'
utimes:'change files modification time to their last commit date'

View file

@ -4,7 +4,6 @@ set __fish_git_extras_commands \
"archive-file:Export the current HEAD of the git repository to an archive" \
"authors:Generate authors report" \
"browse:View the web page for the current repository" \
"browse-ci:View the CI page for the current repository" \
"brv:List branches sorted by their last commit date" \
"bulk:Run git commands on multiple repositories" \
"changelog:Generate a changelog report" \
@ -18,7 +17,6 @@ set __fish_git_extras_commands \
"create-branch:Create branches" \
"delete-branch:Delete branches" \
"delete-merged-branches:Delete merged branches" \
"delete-squashed-branches:Delete squashed branches" \
"delete-submodule:Delete submodules" \
"delete-tag:Delete tags" \
"delta:Lists changed files" \
@ -27,12 +25,11 @@ set __fish_git_extras_commands \
"force-clone:overwrite local repositories with clone" \
"fork:Fork a repo on github" \
"fresh-branch:Create fresh branches" \
"get:Clone a repository in a directory" \
"gh-pages:Create the GitHub Pages branch" \
"graft:Merge and destroy a given branch" \
"guilt:calculate change between two revisions" \
"ignore-io:Get sample gitignore file" \
"ignore:Modify or display .gitignore files" \
"ignore:Add .gitignore patterns" \
"info:Returns information on current repository" \
"local-commits:List local commits" \
"lock:Lock a file excluded from version control" \
@ -50,7 +47,6 @@ set __fish_git_extras_commands \
"rebase-patch:Rebases a patch" \
"release:Commit, tag and push changes to the repository" \
"rename-branch:rename local branch and push to remote" \
"rename-file:rename a file or directory and ensure Git recognizes the change, regardless of filesystem case-sensitivity" \
"rename-remote:Rename a remote" \
"rename-tag:Rename a tag" \
"repl:git read-eval-print-loop" \
@ -72,22 +68,20 @@ set __fish_git_extras_commands \
"unlock:Unlock a file excluded from version control"
# completion for git-extras itself
complete -c git -f -n __fish_git_needs_command -a extras -d 'GIT utilities: repo summary, repl, changelog population, and more'
complete -c git -f -n '__fish_git_needs_command' -a 'extras' -d 'GIT utilities: repo summary, repl, changelog population, and more'
complete -c git -f -n '__fish_git_using_command extras' -s h -l help -d 'Show the help message, can be used for any git-extras commands'
complete -c git -f -n '__fish_git_using_command extras' -s v -l version -d 'Show git-extras version number'
complete -c git -f -n '__fish_git_using_command extras; and not contains -- update (commandline -opc)' -a update -d 'Self update'
complete -c git -f -n '__fish_git_using_command extras; and not contains -- update (commandline -opc)' -a "update" -d 'Self update'
# completion for git-extras provided commands
set __fish_git_extras_commands (printf -- '%s\n' $__fish_git_extras_commands | sed 's/:/\textras:/' | string collect | string escape)
complete -c git -n __fish_git_needs_command -a "$__fish_git_extras_commands"
complete -c git -n '__fish_git_needs_command' -a "$__fish_git_extras_commands"
# authors
complete -c git -f -n '__fish_git_using_command authors' -s l -l list -d 'show authors'
complete -c git -f -n '__fish_git_using_command authors' -l no-email -d 'without email'
# brv
complete -c git -f -n '__fish_git_using_command brv' -s r -l reverse -d 'reverse the sort order'
# bulk
complete -c git -n '__fish_git_using_command bulk' -s a -d 'Run a git command on all workspaces and their repositories'
complete -c git -n '__fish_git_using_command bulk' -s g -d 'Ask the user for confirmation on every execution'
complete -c git -n '__fish_git_using_command bulk' -s a -d 'Run a git command on all workspaces and their repositories'
complete -c git -n '__fish_git_using_command bulk' -s g -d 'Ask the user for confirmation on every execution'
complete -c git -x -n '__fish_git_using_command bulk' -s w -d 'Run on specified workspace'
complete -c git -x -n '__fish_git_using_command bulk' -l addworkspace -d 'Register a workspace for builk operations'
complete -c git -x -n '__fish_git_using_command bulk; and contains addworkspace (commandline -opc)' -l addworkspace -d 'the URL or file with URLs to be added'
@ -106,41 +100,12 @@ complete -c git -f -n '__fish_git_using_command changelog' -s n -l no-merges -d
complete -c git -f -n '__fish_git_using_command changelog' -s m -l merges-only -d 'Uses only merge commits (commits with more than 1 parent) for generated changelog'
complete -c git -f -n '__fish_git_using_command changelog' -s p -l prune-old -d 'Replace existing changelog entirely with newly generated content'
complete -c git -f -n '__fish_git_using_command changelog' -s x -l stdout -d 'Write output to stdout instead of to a new changelog file'
# coauthor
function __fish_git_arg_number -a number
set -l cmd (commandline -opc)
test (count $cmd) -eq $number
end
function __fish_git_extra_coauthor_name
for line in (git authors --list)
printf '%s\n' $line | string replace --regex ' <.*' ''
end
end
function __fish_git_extra_coauthor_email
set -l cmd (commandline -opc)
# name provided in the previous positional argument
set -l name $cmd[3]
for line in (git authors --list)
set -l loop_name (printf '%s\n' $line | string replace --regex ' <.*' '')
if test "$name" = "$loop_name"
printf '%s\n' $line | string replace --regex '.*?<' '' | string replace --regex '>.*?' ''
end
end
end
complete -c git -f -n '__fish_git_using_command coauthor; and __fish_git_arg_number 2' -a '(__fish_git_extra_coauthor_name)'
complete -c git -f -n '__fish_git_using_command coauthor; and __fish_git_arg_number 3' -a '(__fish_git_extra_coauthor_email)'
# commits-since
complete -c git -f -n '__fish_git_using_command commits-since' -s r -l ref -d 'show commits since ref'
# count
complete -c git -f -n '__fish_git_using_command count' -l all -d 'detailed commit count'
# create-branch
complete -c git -x -n '__fish_git_using_command create-branch' -s r -l remote -a '(__fish_git_unique_remote_branches)' -d 'setup remote tracking branch'
# delete-branch
complete -c git -x -n '__fish_git_using_command delete-branch' -a '(__fish_git_branches)' -d 'branch to delete'
# delete-squashed-branches
complete -c git -x -n '__fish_git_using_command delete-squashed-branches' -a '(__fish_git_branches)' -d 'branch to target for squashed merges'
# delete-submodule
complete -c git -x -n "__fish_git_using_command delete-submodule" -a "(__fish_git submodule status 2>/dev/null | string trim | cut -d ' ' -f 2)" -d 'submodule to delete'
# delete-tag
@ -149,24 +114,22 @@ complete -c git -x -n "__fish_git_using_command delete-tag" -a '(__fish_git for-
complete -c git -f -n '__fish_git_using_command effort' -l above -d 'ignore file with less than x commits'
# feature
complete -c git -x -n '__fish_git_using_command feature' -s a -l alias -d 'use branch_prefix instead of feature'
complete -c git -f -n '__fish_git_using_command feature; and not contains -- finish (commandline -opc)' -a finish -d 'merge and delete the feature branch'
complete -c git -f -n '__fish_git_using_command feature; and not contains -- finish (commandline -opc)' -a "finish" -d 'merge and delete the feature branch'
complete -c git -f -n '__fish_git_using_command feature; and contains -- finish (commandline -opc)' -l squash -d 'Run a squash merge'
complete -c git -x -n '__fish_git_using_command feature; and contains -- finish (commandline -opc)' -a '(__fish_git for-each-ref --format="%(refname)" 2>/dev/null | grep "refs/heads/feature")' -d 'name of feature branch'
complete -c git -x -n '__fish_git_using_command feature; and not contains -- finish (commandline -opc)' -s r -l remote -a '(__fish_git_unique_remote_branches)' -d 'Setup a remote tracking branch'
# graft
complete -c git -x -n '__fish_git_using_command graft' -s r -l remote -a '(__fish_git_branches)' -d src-branch-name
complete -c git -x -n '__fish_git_using_command graft' -s r -l remote -a '(__fish_git_branches)' -d dest-branch-name
complete -c git -x -n '__fish_git_using_command graft' -s r -l remote -a '(__fish_git_branches)' -d 'src-branch-name'
complete -c git -x -n '__fish_git_using_command graft' -s r -l remote -a '(__fish_git_branches)' -d 'dest-branch-name'
# guilt
complete -c git -f -n '__fish_git_using_command guilt' -s w -l ignore-whitespace -d 'ignore whitespace only changes'
complete -c git -f -n '__fish_git_using_command guilt' -s e -l email -d 'display author emails instead of names'
complete -c git -f -n '__fish_git_using_command guilt' -s d -l debug -d 'output debug information'
complete -c git -f -n '__fish_git_using_command guilt' -s h -d 'output usage information'
complete -c git -f -n '__fish_git_using_command guilt' -s h -d 'output usage information'
# ignore
complete -c git -f -n '__fish_git_using_command ignore' -s l -l local -d 'set context to local gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s g -l global -d 'set context to global gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s p -l private -d 'set context to private gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s e -l edit -d 'set action to edit'
complete -c git -f -n '__fish_git_using_command ignore' -s r -l remove -d 'set action to remove'
complete -c git -f -n '__fish_git_using_command ignore' -s l -l local -d 'show local gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s g -l global -d 'show global gitignore'
complete -c git -f -n '__fish_git_using_command ignore' -s p -l private -d 'show repo gitignore'
# ignore-io
function __fish_git_extra_get_ignore_io_types
# we will first remove every tab spaces, and then append `\t` at the end to remove the default description
@ -181,35 +144,32 @@ complete -c git -x -n '__fish_git_using_command ignore-io' -s s -l search -d 'se
complete -c git -x -n '__fish_git_using_command ignore-io' -s t -l show-update-time -d 'Show the last modified time of ~/.gi_list'
complete -c git -x -n '__fish_git_using_command ignore-io' -s u -l update -d 'Update ~/.gi_list'
# merge-into
complete -c git -n '__fish_git_using_command merge-into' -l ff-only -d 'merge only fast-forward'
complete -c git -n '__fish_git_using_command merge-into' -l ff-only -d 'merge only fast-forward'
complete -c git -x -n '__fish_git_using_command merge-into' -a '(__fish_git_branches)'
# missing
complete -c git -x -n '__fish_git_using_command missing' -a '(__fish_git_branches)'
# rename-file
complete -c git -f -n '__fish_git_using_command rename-file' -s h -l help -d 'Show usage information'
# squash
complete -c git -x -n '__fish_git_using_command squash' -a '(__fish_git_branches)'
complete -c git -x -n '__fish_git_using_command squash' -l squash-msg -d 'commit with the squashed commit messages'
# stamp
complete -c git -x -n '__fish_git_using_command stamp' -s r -l replace -d 'replace stamps with same id'
# standup
complete -c git -x -n '__fish_git_using_command standup' -s a -d 'Specify the author of commits. Use all to specify all authors'
complete -c git -x -n '__fish_git_using_command standup' -s a -d 'Specify the author of commits. Use "all" to specify all authors'
complete -c git -x -n '__fish_git_using_command standup' -s m -d 'The depth of recursive directory search'
complete -c git -x -n '__fish_git_using_command standup' -s d -d 'Show history since N days ago'
complete -c git -x -n '__fish_git_using_command standup' -s D -d 'Specify the date format displayed in commit history'
complete -c git -n '__fish_git_using_command standup' -s f -d 'Fetch commits before showing history'
complete -c git -n '__fish_git_using_command standup' -s g -d 'Display GPG signed info'
complete -c git -n '__fish_git_using_command standup' -s h -l help -d 'Display help message'
complete -c git -n '__fish_git_using_command standup' -s L -d 'Enable the inclusion of symbolic links'
complete -c git -n '__fish_git_using_command standup' -s B -d 'Display the commits in branch group'
complete -c git -n '__fish_git_using_command standup' -s f -d 'Fetch commits before showing history'
complete -c git -n '__fish_git_using_command standup' -s g -d 'Display GPG signed info'
complete -c git -n '__fish_git_using_command standup' -s h -l help -d 'Display help message'
complete -c git -n '__fish_git_using_command standup' -s L -d 'Enable the inclusion of symbolic links'
complete -c git -n '__fish_git_using_command standup' -s B -d 'Display the commits in branch group'
complete -c git -x -n '__fish_git_using_command standup' -s n -d 'Limit the number of commits displayed per group'
# summary
complete -c git -n '__fish_git_using_command summary' -l line -d 'summarize with lines rather than commits'
complete -c git -n '__fish_git_using_command summary' -l dedup-by-email -d 'remove duplicate users by the email address'
complete -c git -n '__fish_git_using_command summary' -l no-merges -d 'exclude merge commits'
complete -c git -n '__fish_git_using_command summary' -l line -d 'summarize with lines rather than commits'
complete -c git -n '__fish_git_using_command summary' -l dedup-by-email -d 'remove duplicate users by the email address'
# release
complete -c git -x -n '__fish_git_using_command release' -s c -d 'Generates/populates the changelog with all commit message since the last tag'
complete -c git -x -n '__fish_git_using_command release' -s r -d 'The remote repository that is destination of a push operation'
complete -c git -x -n '__fish_git_using_command release' -s r -d 'The "remote" repository that is destination of a push operation'
complete -c git -x -n '__fish_git_using_command release' -s m -d 'use the custom commit information instead of the default message'
complete -c git -x -n '__fish_git_using_command release' -s s -d 'Create a signed and annotated tag'
complete -c git -x -n '__fish_git_using_command release' -s u -d 'Create a tag, annotated and signed with the given key'
@ -218,3 +178,5 @@ complete -c git -x -n '__fish_git_using_command release' -l no-empty-commit -d '
# undo
complete -c git -x -n '__fish_git_using_command undo' -s s -l soft -d 'only rolls back the commit but changes remain un-staged'
complete -c git -x -n '__fish_git_using_command undo' -s h -l hard -d 'wipes your commit(s)'

View file

@ -6,14 +6,11 @@ git_extra_mktemp() {
}
git_extra_default_branch() {
local extras_default_branch init_default_branch
extras_default_branch=$(git config --get git-extras.default-branch)
init_default_branch=$(git config --get init.defaultBranch)
if [ -n "$extras_default_branch" ]; then
echo "$extras_default_branch"
elif [ -n "$init_default_branch" ]; then
echo "$init_default_branch"
local default_branch
default_branch=$(git config --get git-extras.default-branch)
if [ -z "$default_branch" ]; then
echo "master"
else
echo "main"
echo "$default_branch"
fi
}

View file

@ -3,9 +3,7 @@
#
is_git_repo() {
# --git-dir succeeds for both normal and bare repositories, whereas
# --show-toplevel fails inside a bare repository (it has no working tree).
git rev-parse --git-dir > /dev/null 2>&1
git rev-parse --show-toplevel > /dev/null 2>&1
result=$?
if test $result != 0; then
>&2 echo 'Not a git repo!'

View file

@ -1,2 +1,2 @@
# reset environment variables that could interfere with normal usage
unset -v GREP_OPTIONS
export GREP_OPTIONS=

View file

@ -39,34 +39,13 @@ goto :defaultpath
rem remove the last slash
SET bindir=%bindir:~0,-1%
for %%G in ("%bindir%") do set installdir=%%~dpG
rem strip a trailing slash so we can inspect the leaf directory name
if "%installdir:~-1%"=="\" set installdir=%installdir:~0,-1%
rem git.exe found under <GitRoot>\mingw64\bin or <GitRoot>\clangarm64\bin
rem means installdir already is the architecture directory itself
for %%G in ("%installdir%") do set archdir=%%~nxG
if /I "%archdir%"=="mingw64" (
set PREFIX=%installdir%
) else if /I "%archdir%"=="clangarm64" (
set PREFIX=%installdir%
) else if exist "%installdir%\mingw64" (
set PREFIX=%installdir%\mingw64
) else if exist "%installdir%\clangarm64" (
set PREFIX=%installdir%\clangarm64
) else (
set PREFIX=%installdir%\mingw64
)
set PREFIX=%installdir%mingw64
goto :foundprefix
:defaultpath
:: default for Git for Windows 2.x
if exist "%ProgramFiles%\Git" (
if exist "%ProgramFiles%\Git\mingw64" (
set PREFIX=%ProgramFiles%\Git\mingw64
) else if exist "%ProgramFiles%\Git\clangarm64" (
set PREFIX=%ProgramFiles%\Git\clangarm64
) else (
set PREFIX=%ProgramFiles%\Git\mingw64
)
set PREFIX=%ProgramFiles%\Git\mingw64
)
:foundprefix
@ -76,11 +55,9 @@ IF NOT "%~1"=="" (
REM just supplying the git dir is enough...
if exist "%~1\mingw64" (
set PREFIX=%~1\mingw64
) else if exist "%~1\clangarm64" (
set PREFIX=%~1\clangarm64
) else (
echo Using git install path "%~1" as PREFIX, please make sure it's really a
echo path to the mingw64 or clangarm64 directory...
echo path to the mingw64 directory...
echo.
SET PREFIX=%~1
)
@ -95,14 +72,12 @@ set GIT_INSTALL_DIR=!GIT_INSTALL_DIR:"=!
IF %GIT_INSTALL_DIR:~-1%==\ SET GIT_INSTALL_DIR=%GIT_INSTALL_DIR:~0,-1%
if not exist "%GIT_INSTALL_DIR%\mingw64" (
if not exist "%GIT_INSTALL_DIR%\clangarm64" (
echo No mingw64 or clangarm64 folder found in %GIT_INSTALL_DIR%.
echo.
echo Please supply a proper "Git for Windows 2.x" install path:
echo "install.cmd c:\[git-install-path]"
set ERROR=1
goto :exit
)
echo No mingw64 folder found in %GIT_INSTALL_DIR%.
echo.
echo Please supply a proper "Git for Windows 2.x" install path:
echo "install.cmd c:\[git-install-path]"
set ERROR=1
goto :exit
)
echo Installing to %PREFIX%
@ -141,7 +116,7 @@ FOR /R "%GITEXTRAS%\bin" %%i in (*.*) DO (
TYPE "%GITEXTRAS%\helper\reset-env" >> "%PREFIX%\bin\%%~ni"
TYPE "%GITEXTRAS%\helper\git-extra-utility" >> "%PREFIX%\bin\%%~ni"
TYPE "%GITEXTRAS%\helper\is-git-repo" >> "%PREFIX%\bin\%%~ni"
REM Added /E option for installation fix on Windows 10.0.17134 and higher
MORE /E +2 "%GITEXTRAS%\bin\%%~ni" >> "%PREFIX%\bin\%%~ni"
)
@ -152,7 +127,7 @@ FOR %%i in (%COMMANDS_WITHOUT_REPO%) DO (
ECHO #^^!/usr/bin/env bash > "%PREFIX%\bin\%%i"
TYPE "%GITEXTRAS%\helper\reset-env" >> "%PREFIX%\bin\%%i"
TYPE "%GITEXTRAS%\helper\git-extra-utility" >> "%PREFIX%\bin\%%i"
REM Added /E option for installation fix on Windows 10.0.17134 and higher
MORE /E +2 "%GITEXTRAS%\bin\%%i" >> "%PREFIX%\bin\%%i"
)

View file

@ -1,19 +0,0 @@
.\" generated with Ronn-NG/v0.8.0
.\" http://github.com/apjanke/ronn-ng/tree/0.8.0
.TH "GIT\-ABORT" "1" "August 2020" "" "Git Extras"
.SH "NAME"
\fBgit\-abort\fR \- Abort current git operation
.SH "SYNOPSIS"
\fBgit\-abort\fR
.SH "DESCRIPTION"
Abort current git revert, rebase, merge or cherry\-pick process\.
.SH "OPTIONS"
There are no options, it just aborts current operation\.
.SH "EXAMPLES"
\fBgit\-abort\fR
.SH "AUTHOR"
Written by Przemek Kitszel <\fI\%mailto:pkitszel@gmail\.com\fR>
.SH "REPORTING BUGS"
<\fI\%https://github\.com/tj/git\-extras/issues\fR>
.SH "SEE ALSO"
<\fI\%https://github\.com/tj/git\-extras\fR>

View file

@ -1,114 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv='content-type' content='text/html;charset=utf8'>
<meta name='generator' content='Ronn-NG/v0.8.0 (http://github.com/apjanke/ronn-ng/tree/0.8.0)'>
<title>git-abort(1) - Abort current git operation</title>
<style type='text/css' media='all'>
/* style: man */
body#manpage {margin:0}
.mp {max-width:100ex;padding:0 9ex 1ex 4ex}
.mp p,.mp pre,.mp ul,.mp ol,.mp dl {margin:0 0 20px 0}
.mp h2 {margin:10px 0 0 0}
.mp > p,.mp > pre,.mp > ul,.mp > ol,.mp > dl {margin-left:8ex}
.mp h3 {margin:0 0 0 4ex}
.mp dt {margin:0;clear:left}
.mp dt.flush {float:left;width:8ex}
.mp dd {margin:0 0 0 9ex}
.mp h1,.mp h2,.mp h3,.mp h4 {clear:left}
.mp pre {margin-bottom:20px}
.mp pre+h2,.mp pre+h3 {margin-top:22px}
.mp h2+pre,.mp h3+pre {margin-top:5px}
.mp img {display:block;margin:auto}
.mp h1.man-title {display:none}
.mp,.mp code,.mp pre,.mp tt,.mp kbd,.mp samp,.mp h3,.mp h4 {font-family:monospace;font-size:14px;line-height:1.42857142857143}
.mp h2 {font-size:16px;line-height:1.25}
.mp h1 {font-size:20px;line-height:2}
.mp {text-align:justify;background:#fff}
.mp,.mp code,.mp pre,.mp pre code,.mp tt,.mp kbd,.mp samp {color:#131211}
.mp h1,.mp h2,.mp h3,.mp h4 {color:#030201}
.mp u {text-decoration:underline}
.mp code,.mp strong,.mp b {font-weight:bold;color:#131211}
.mp em,.mp var {font-style:italic;color:#232221;text-decoration:none}
.mp a,.mp a:link,.mp a:hover,.mp a code,.mp a pre,.mp a tt,.mp a kbd,.mp a samp {color:#0000ff}
.mp b.man-ref {font-weight:normal;color:#434241}
.mp pre {padding:0 4ex}
.mp pre code {font-weight:normal;color:#434241}
.mp h2+pre,h3+pre {padding-left:0}
ol.man-decor,ol.man-decor li {margin:3px 0 10px 0;padding:0;float:left;width:33%;list-style-type:none;text-transform:uppercase;color:#999;letter-spacing:1px}
ol.man-decor {width:100%}
ol.man-decor li.tl {text-align:left}
ol.man-decor li.tc {text-align:center;letter-spacing:4px}
ol.man-decor li.tr {text-align:right;float:right}
</style>
</head>
<!--
The following styles are deprecated and will be removed at some point:
div#man, div#man ol.man, div#man ol.head, div#man ol.man.
The .man-page, .man-decor, .man-head, .man-foot, .man-title, and
.man-navigation should be used instead.
-->
<body id='manpage'>
<div class='mp' id='man'>
<div class='man-navigation' style='display:none'>
<a href="#NAME">NAME</a>
<a href="#SYNOPSIS">SYNOPSIS</a>
<a href="#DESCRIPTION">DESCRIPTION</a>
<a href="#OPTIONS">OPTIONS</a>
<a href="#EXAMPLES">EXAMPLES</a>
<a href="#AUTHOR">AUTHOR</a>
<a href="#REPORTING-BUGS">REPORTING BUGS</a>
<a href="#SEE-ALSO">SEE ALSO</a>
</div>
<ol class='man-decor man-head man head'>
<li class='tl'>git-abort(1)</li>
<li class='tc'>Git Extras</li>
<li class='tr'>git-abort(1)</li>
</ol>
<h2 id="NAME">NAME</h2>
<p class="man-name">
<code>git-abort</code> - <span class="man-whatis">Abort current git operation</span>
</p>
<h2 id="SYNOPSIS">SYNOPSIS</h2>
<p><code>git-abort</code></p>
<h2 id="DESCRIPTION">DESCRIPTION</h2>
<p> Abort current git revert, rebase, merge or cherry-pick process.</p>
<h2 id="OPTIONS">OPTIONS</h2>
<p> There are no options, it just aborts current operation.</p>
<h2 id="EXAMPLES">EXAMPLES</h2>
<p> <code>git-abort</code></p>
<h2 id="AUTHOR">AUTHOR</h2>
<p>Written by Przemek Kitszel &lt;<a href="mailto:pkitszel@gmail.com" data-bare-link="true">pkitszel@gmail.com</a>&gt;</p>
<h2 id="REPORTING-BUGS">REPORTING BUGS</h2>
<p>&lt;<a href="https://github.com/tj/git-extras/issues" data-bare-link="true">https://github.com/tj/git-extras/issues</a>&gt;</p>
<h2 id="SEE-ALSO">SEE ALSO</h2>
<p>&lt;<a href="https://github.com/tj/git-extras" data-bare-link="true">https://github.com/tj/git-extras</a>&gt;</p>
<ol class='man-decor man-foot man foot'>
<li class='tl'></li>
<li class='tc'>August 2020</li>
<li class='tr'>git-abort(1)</li>
</ol>
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show more