feat(scp): add -v/--verbose and -i/--interactive flags

git scp/git rscp printed a diff via plain `git diff`/`git diff --stat`
with no `--no-pager` and no TTY check, blocking on the user's pager.
Add -v/--verbose to print the diff via --no-pager before syncing, and
-i/--interactive to also prompt for confirmation before the real
push/copy. Both apply to git scp and git rscp, and must precede
<remote>.

Updates man/git-scp.md and Commands.md.
This commit is contained in:
AJ Côté 2026-07-06 13:32:42 -04:00
parent 184d37e980
commit aef6cc1f48
No known key found for this signature in database
3 changed files with 74 additions and 9 deletions

View file

@ -1203,6 +1203,13 @@ 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)
```
### Examples
Copy unstaged files to remote. Useful when you want to make quick test without making any commits

View file

@ -77,6 +77,16 @@ function _sanitize()
function scp_and_stage
{
local verbose=0 interactive=0
while :
do
case "$1" in
-v|--verbose) verbose=1; shift;;
-i|--interactive) verbose=1; interactive=1; shift;;
*) break;;
esac
done
set_remote "$1"
shift
@ -94,16 +104,26 @@ function scp_and_stage
list=$(git ls-files "$@")" "$(git ls-files -o "$@")
elif [ -n "$refhead" ]
then
git diff --stat "$refhead"
[ "$verbose" -eq 1 ] && git --no-pager diff --stat "$refhead"
list=$(git diff "$refhead" --name-only)
else
git diff
[ "$verbose" -eq 1 ] && git --no-pager 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 ] && { [ -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
if [ -n "$list" ]
then
local _TMP=${0///}
@ -128,12 +148,38 @@ function scp_and_stage
function reverse_scp()
{
local verbose=0 interactive=0
while :
do
case "$1" in
-v|--verbose) verbose=1; shift;;
-i|--interactive) verbose=1; interactive=1; shift;;
*) break;;
esac
done
set_remote "$1"
shift
local _TMP=${0///}
echo "$@" > "$_TMP" &&
rsync -rlDv --files-from="$_TMP" "$(git config "remote.$remote.url")/" ./ &&
echo "$@" > "$_TMP"
if [ "$verbose" -eq 1 ]
then
rsync -rlDvni --files-from="$_TMP" "$(git config "remote.$remote.url")/" ./
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"
}
@ -148,9 +194,13 @@ function _usage()
{
echo "Usage:
git scp -h|help|?
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
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)
"
case $1 in

View file

@ -4,8 +4,8 @@ git-scp(1) -- Copy files to SSH compatible `git-remote`
## SYNOPSIS
`git scp` -h|help|?
`git scp` <remote> [<commits>...|<path>...]
`git rscp` <remote> <path>
`git scp` [options] <remote> [<commits>...|<path>...]
`git rscp` [options] <remote> <path>
## DESCRIPTION
@ -29,6 +29,14 @@ Internally this script uses `rsync` and not `scp` as the name suggests.
The <paths> parameters, when given, are used to limit the diff to the named paths (you can give directory names and get diff for all files under them).
-v, --verbose
Print what will be synced before syncing: the diff for `git scp`, or a preview (rsync dry-run) for `git rscp`.
-i, --interactive
Same as `--verbose`, but also prompt for confirmation before syncing. Implies `--verbose`
## GIT CONFIGS
To sanitize files using `dos2unix` before copying files