git-for-windows / git

A fork of Git containing Windows-specific patches.
http://gitforwindows.org/
Other
8.39k stars 2.54k forks source link

git subtree add/split command throw Unexpected option #1759

Closed Jonkimi closed 6 years ago

Jonkimi commented 6 years ago

Setup

$ git --version --build-options
git version 2.18.0.windows.1
cpu: x86_64
built from commit: cd1a74fc9dc8a07626c216940db9a51f25206e03
sizeof-long: 4
$ cmd.exe /c ver

Microsoft Windows [Version 10.0.14393]
# One of the following:
> type "C:\Program Files\Git\etc\install-options.txt"
> type "C:\Program Files (x86)\Git\etc\install-options.txt"
> type "%USERPROFILE%\AppData\Local\Programs\Git\etc\install-options.txt"
$ cat /etc/install-options.txt

Editor Option: VIM
Path Option: Cmd
SSH Option: OpenSSH
CURL Option: OpenSSL
CRLF Option: CRLFAlways
Bash Terminal Option: MinTTY
Performance Tweaks FSCache: Enabled
Use Credential Manager: Enabled
Enable Symlinks: Disabled

Hopefully, no.

Details

Bash

$ GIT_TRACE=1 git subtree add -P HSSCore HSSCore master
17:32:18.994269 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/bin
17:32:18.997277 git.c:654               trace: exec: git-subtree add -P HSSCore HSSCore master
17:32:18.997277 run-command.c:637       trace: run_command: git-subtree add -P HSSCore HSSCore master
17:32:21.811989 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:21.947353 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:22.590782 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:22.593822 git.c:654               trace: exec: git-sh-i18n--envsubst --variables 'usage: $dashless $USAGE'
17:32:22.593822 run-command.c:637       trace: run_command: git-sh-i18n--envsubst --variables 'usage: $dashless $USAGE'
17:32:22.630887 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:22.746227 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:22.748233 git.c:654               trace: exec: git-sh-i18n--envsubst 'usage: $dashless $USAGE'
17:32:22.748233 run-command.c:637       trace: run_command: git-sh-i18n--envsubst 'usage: $dashless $USAGE'
17:32:22.785298 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:23.089107 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:23.090109 git.c:415               trace: built-in: git rev-parse --git-dir
17:32:23.227475 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:23.228503 git.c:415               trace: built-in: git rev-parse --show-cdup
17:32:23.416013 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:32:23.417010 git.c:415               trace: built-in: git rev-parse --git-path objects
Options: add -P HSSCore HSSCore master
Unexpected option: add

I add echo "Options: $*" in line 80 of C:\Program Files\Git\mingw64\libexec\git-core\git-subtree

...
assert () {
    if ! "$@"
    then
        die "assertion failed: " "$@"
    fi
}

echo "Options: $*"

while test $# -gt 0
...

operation success.

operation failed.

I ran same command succeed on Linux, so I modified this command and run success according to Options output on Linux

Modified Command and Operation Output:

 $ GIT_TRACE=1 git subtree -P HSSCore -- add HSSCore master
17:41:01.979943 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/bin
17:41:01.982951 git.c:654               trace: exec: git-subtree -P HSSCore -- add HSSCore master
17:41:01.982951 run-command.c:637       trace: run_command: git-subtree -P HSSCore -- add HSSCore master
17:41:02.607146 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:02.765534 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:03.406959 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:03.408964 git.c:654               trace: exec: git-sh-i18n--envsubst --variables 'usage: $dashless $USAGE'
17:41:03.408964 run-command.c:637       trace: run_command: git-sh-i18n--envsubst --variables 'usage: $dashless $USAGE'
17:41:03.454084 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:03.583428 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:03.590447 git.c:654               trace: exec: git-sh-i18n--envsubst 'usage: $dashless $USAGE'
17:41:03.590447 run-command.c:637       trace: run_command: git-sh-i18n--envsubst 'usage: $dashless $USAGE'
17:41:03.629550 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:03.975470 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:03.976473 git.c:415               trace: built-in: git rev-parse --git-dir
17:41:04.129881 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:04.130884 git.c:415               trace: built-in: git rev-parse --show-cdup
17:41:04.334425 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:04.335427 git.c:415               trace: built-in: git rev-parse --git-path objects
Options: -P HSSCore -- add HSSCore master
17:41:04.730478 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:04.734489 git.c:415               trace: built-in: git diff-index HEAD --exit-code --quiet
17:41:04.900932 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:04.903939 git.c:415               trace: built-in: git diff-index --cached HEAD --exit-code --quiet
17:41:05.036292 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:05.037294 git.c:415               trace: built-in: git check-ref-format refs/heads/master
git fetch HSSCore master
17:41:05.155608 exec-cmd.c:236          trace: resolved executable dir: C:/Program Files/Git/mingw64/libexec/git-core
17:41:05.159619 git.c:415               trace: built-in: git fetch HSSCore master

Command and Operation Output on Linux

$ GIT_TRACE=1 git subtree add -P HSSCore HSSCore master
trace: exec: 'git-subtree' 'add' '-P' 'HSSCore' 'HSSCore' 'master'
trace: run_command: 'git-subtree' 'add' '-P' 'HSSCore' 'HSSCore' 'master'
trace: built-in: git 'rev-parse' '--parseopt' '--' 'add' '-P' 'HSSCore' 'HSSCore' 'master'
trace: built-in: git 'rev-parse' '--git-dir'
trace: built-in: git 'rev-parse' '--show-cdup'
Options: -P HSSCore -- add HSSCore master
trace: built-in: git 'diff-index' 'HEAD' '--exit-code' '--quiet'
trace: built-in: git 'diff-index' '--cached' 'HEAD' '--exit-code' '--quiet'
trace: built-in: git 'rev-parse' '-q' '--verify' 'master^{commit}'
git fetch HSSCore master
trace: built-in: git 'fetch' 'HSSCore' 'master'
dscho commented 6 years ago

git subtree add -P HSSCore HSSCore master

I don't have HSSCore.

The idea of a Minimal, Verifiable, Complete Example is that it makes it easy for other people to verify your claim that Git is broken.

So a small public repository would do just fine.

As it is, you're in luck (at least half-lucky), as the git-subtree command already comes with tests. I say half-lucky because they work for me.

But they do suggest that something goes wrong in your setup (something we saw earlier, in git stash's context). To see what I mean, just add the set -x somewhere after the #!/bin/sh line in git-subtree and call the command again that fails for you. You should see something similar to this:

++ git rev-parse --parseopt -- add '--prefix=sub dir' FETCH_HEAD
+ eval 'set -- -P '\''sub dir'\'' -- '\''add'\'' '\''FETCH_HEAD'\'''
++ set -- -P 'sub dir' -- add FETCH_HEAD

Except that in your case, it probably says eval ''. I strongly suspect this to be the case, as we saw exactly this symptom before, at least with git stash and with git flow: some overzealous anti-malware (most often, Comodo Internet Security) thought that the sub shell called here indicates some sort of shellcode exploit, and simply shuts down the git rev-parse subprocess (and since git subtree is a Unix shell script, like so many Unix shell scripts, it does not really get error checking right and fails to pick up on the shut down process), so git subtree goes on and tries to use what it thinks is not an empty string.

But it is an empty string, so the git rev-parse --parseopt function never has a chance of normalizing the command-line, and therefore the command-parsing of git-subtree gets thoroughly confused (because the -- is missing that git rev-parse --parseopt would have inserted at the appropriate spot).

Probably you have Comodo Internet Security?

Jonkimi commented 6 years ago

The idea of a Minimal, Verifiable, Complete Example is that it makes it easy for other people to verify your claim that Git is broken.

Thank you for your advice, I will do better.

It did say eval '' after I added set -x in git-subtree . And I have Comodo Internet Security.

The output after I added set -x in git-subtree :

+ test 5 -eq 0
+ OPTS_SPEC='git subtree add   --prefix=<prefix> <commit>
git subtree add   --prefix=<prefix> <repository> <ref>
git subtree merge --prefix=<prefix> <commit>
git subtree pull  --prefix=<prefix> <repository> <ref>
git subtree push  --prefix=<prefix> <repository> <ref>
git subtree split --prefix=<prefix> <commit...>
--
h,help        show the help
q             quiet
d             show debug messages
P,prefix=     the name of the subdir to split out
m,message=    use the given message as the commit message for the merge commit
 options for '\''split'\''
annotate=     add a prefix to commit message of new commits
b,branch=     create a new branch from the split subtree
ignore-joins  ignore prior --rejoin commits
onto=         try connecting new tree to an existing one
rejoin        merge the new branch back into HEAD
 options for '\''add'\'', '\''merge'\'', and '\''pull'\''
squash        merge subtree changes as a single commit
'
+ eval ''
++ git --exec-path
+ PATH='/mingw64/libexec/git-core:/mingw64/bin:/usr/bin:/c/Users/liaojun/bin:/c/Program Files (x86)/Common Files/Oracle/Java/javapath:/c/Program Files (x86)/Eziriz/.NET Reactor:/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0/bin:/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.0/libnvvp:/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.1/bin:/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.1/libnvvp:/c/Program Files (x86)/Common Files/Intel/Shared Libraries/redist/intel64/compiler:/d/Program Files/Python/Python36/Scripts:/d/Program Files/Python/Python36:/c/ProgramData/Oracle/Java/javapath:/c/Windows/system32:/c/Windows:/c/Windows/System32/Wbem:/c/Windows/System32/WindowsPowerShell/v1.0:/c/Program Files (x86)/NVIDIA Corporation/PhysX/Common:/c/Users/liaojun/.dnx/bin:/c/Program Files/Microsoft DNX/Dnvm:/c/Program Files/Microsoft SQL Server/120/Tools/Binn:/c/Program Files/Microsoft SQL Server/130/Tools/Binn:/c/Program Files/dotnet:/c/Program Files (x86)/Windows Kits/8.1/Windows Performance Toolkit:/c/Go/bin:/c/ProgramData/chocolatey/bin:/c/Program Files (x86)/vim/vim80:/d/06-software/colortool:/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.1/bin:/c/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v9.1/libnvvp:/c/Program Files/NVIDIA Corporation/Nsmi:/c/Program Files (x86)/nodejs:/d/Program Files/MacType:/c/Program Files (x86)/Common Files/Thunder Network/KanKan/Codecs:/c/Program Files/Microsoft Windows Performance Toolkit:/c/mingw-w64/mingw32/bin:/c/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin:/c/Program Files/Microsoft SQL Server/110/Tools/Binn:/c/Program Files (x86)/Microsoft SDKs/TypeScript/1.0:/c/Program Files/Intel/WiFi/bin:/c/Program Files/Common Files/Intel/WirelessCommon:/cmd:/c/Program Files/NVIDIA Corporation/Nsmi:/c/Program Files/Microsoft VS Code/bin:/d/Program Files/Python/Python36/Scripts:/d/Program Files/Python/Python36:/c/Users/liaojun/AppData/Local/Microsoft/WindowsApps:/c/Program Files/Microsoft VS Code/bin:/c/Program Files/CMake/bin:/c/Users/liaojun/.babun:/c/Users/liaojun/AppData/Roaming/npm:/c/Program Files (x86)/Nmap:/c/Program Files/Intel/WiFi/bin:/c/Program Files/Common Files/Intel/WirelessCommon:/c/Program Files/NVIDIA Corporation/Nsmi:C:/Program Files/Git/mingw64/libexec/git-core'
+ . git-sh-setup
++ unset CDPATH
++ IFS='
'
+++ git --exec-path
++ . 'C:/Program Files/Git/mingw64/libexec/git-core/git-sh-i18n'
+++ TEXTDOMAIN=git
+++ export TEXTDOMAIN
+++ test -z ''
+++ TEXTDOMAINDIR=/mingw64/share/locale
+++ export TEXTDOMAINDIR
+++ GIT_INTERNAL_GETTEXT_SH_SCHEME=fallthrough
+++ test -n ''
+++ test -n fallthrough
+++ GIT_INTERNAL_GETTEXT_SH_SCHEME=fallthrough
+++ export GIT_INTERNAL_GETTEXT_SH_SCHEME
+++ case "$GIT_INTERNAL_GETTEXT_SH_SCHEME" in
++ GIT_QUIET=
++ test -n ''
++ dashless=
++ '[' -z '' ']'
+++ eval_gettext 'usage: $dashless $USAGE'
+++ printf %s 'usage: $dashless $USAGE'
++++ git sh-i18n--envsubst --variables 'usage: $dashless $USAGE'
+++ export PATH dashless USAGE
+++ git sh-i18n--envsubst 'usage: $dashless $USAGE'
++ LONG_USAGE='usage:  '
++ case "$1" in
++ case $(uname -s) in
+++ uname -s
++ test -x /usr/bin/sort
++ test -x /usr/bin/find
++ type builtin
++ test -z ''
++ git_dir_init
+++ git rev-parse --git-dir
++ GIT_DIR=.git
++ '[' -z '' ']'
+++ git rev-parse --show-cdup
++ test -z ''
++ test -n .git
+++ cd .git
+++ pwd
+++ builtin pwd -W
++ GIT_DIR=G:/05-code/04-C#/hotelSelfSys/.git
+++ git rev-parse --git-path objects
++ : .git/objects
+ require_work_tree
++ git rev-parse --is-inside-work-tree
+ test true = true
+ quiet=
+ branch=
+ debug=
+ command=
+ onto=
+ rejoin=
+ ignore_joins=
+ annotate=
+ squash=
+ message=
+ prefix=
+ echo 'Options: add -P HSSCore HSSCore master'
Options: add -P HSSCore HSSCore master
+ test 5 -gt 0
+ opt=add
+ shift
+ case "$opt" in
+ die 'Unexpected option: add'
+ die_with_status 1 'Unexpected option: add'
+ status=1
+ shift
+ printf '%s\n' 'Unexpected option: add'
Unexpected option: add
+ exit 1