Git development
 help / color / mirror / Atom feed
* directory / submodule merge conflcts
From: Mark Levedahl @ 2008-07-12 16:01 UTC (permalink / raw)
  To: Git Mailing List

Over time, I have converted a number of subdirectories in a main project 
into submodules, while maintaining the complete pathnames intact. Thus, 
only git knows that an object at code/dir1 is a submodule or a 
subdirectory of the superproject.

git has trouble merging branches across the above boundaries, the script 
below demonstrates the issue. I cannot merge the main branch and a 
branch that occurred before conversion to a submodule.

Paraphrasing the script, the formula is
    - create a superproject with a subdirectory (sub1)
    - on master, convert sub1 to a submodule (no other changes)
    - on branch base (before sub1 conversion to a submodule), change a 
file not in sub1 (no other changes)
    - merge master into base - failure

The actual reported error message is:
fatal: cannot read object b500f4d0c6aaf40a0251da35b82c0fa5c57b6503 
'sub1~master': It is a submodule!
Merge with strategy recursive failed.

Any ideas or hints on how to improve this would be greatly appreciated.

Thanks,
Mark

#!/bin/sh
#
# demonstrate issue with directory / submodule (D/S) conflict problem

mkdir dsprob || exit
cd dsprob
git init
mkdir sub1
echo hi > foo
echo hi1 > sub1/foo
git add .
git commit -m "Create base"
git checkout -b base
echo bye >> foo
git add .
git commit -m "Modify base"
git checkout master

# make sub1 a submodule
git rm -r -f sub1
git commit -m "removed sub1 directory"
git checkout base sub1
git reset
cd sub1
git init
git add .
git commit -m "Start sub1 as its own project"
cd ..
mv sub1 sub1_repo
git submodule add "$(pwd)/sub1_repo" sub1
git commit -m "Added sub1 as a submodule"

# now, go back to base and try to merge
rm -rf sub1
git checkout -f base
git merge master

^ permalink raw reply

* [RFH] Finding all commits that touch the same files as a specific commit
From: Sverre Rabbelier @ 2008-07-12 15:58 UTC (permalink / raw)
  To: Git Mailinglist

Heya,

Currently I do the following:
$git diff-tree --name-status --no-commit-id -r <hash>
To get all the files touched by the commit, I do:
$git rev-list HEAD -- all the returned paths here
This works perfectly, except when the subtree merge strategy is used,
since in that case I get (example from git.git):
$ git diff-tree --name-status --no-commit-id -r
5821988f97b827f6ba81dfeebff932067c88ba6c
M	git-gui.sh
M	lib/diff.tcl
$ git rev-list HEAD -- git-gui.sh lib/diff.tcl
$

Now it was noticed on #git that git log has a --follow argument which
-does- catch the rename, but it only works on one file at a time. So,
my question is this:
How do I find all commits that touch the same files as a specific commit?
I have described my current approach above, which does not work when
the subtree merge strategy is used. I am not stuck to this approach
though, if someone comes up with a better way to do this than with
'git diff-tree' / 'git rev-list' I'm fine by that. I provided with my
current approach in the hope that someone comes up with a similar
solution which means I'll have to edit less ;).

-- 
Cheers,

Sverre Rabbelier

^ permalink raw reply

* [PATCH 2/2] t/: Use "test_must_fail git" instead of "! git"
From: Stephan Beyer @ 2008-07-12 15:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Stephan Beyer
In-Reply-To: <1215877672-17049-1-git-send-email-s-beyer@gmx.net>

This patch changes every occurrence of "! git" -- with the meaning
that a git call has to fail -- into "test_must_fail git".

This is useful to
 - make sure the test does not fail because of a signal,
   e.g. SIGSEGV, and
 - advertise the use of "test_must_fail" for new tests.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---

Because test_must_fail has been introduced by Junio, this patch
is only "To:"'ed to him and not to all the authors of the test
cases. I hope this is ok. ;)

 t/t0000-basic.sh                          |    6 +-
 t/t0020-crlf.sh                           |    8 ++--
 t/t0050-filesystem.sh                     |    2 +-
 t/t1200-tutorial.sh                       |    2 +-
 t/t1300-repo-config.sh                    |   19 ++++----
 t/t1302-repo-version.sh                   |    2 +-
 t/t1400-update-ref.sh                     |    4 +-
 t/t2000-checkout-cache-clash.sh           |    2 +-
 t/t2100-update-cache-badpath.sh           |    2 +-
 t/t3020-ls-files-error-unmatch.sh         |    2 +-
 t/t3200-branch.sh                         |    8 ++--
 t/t3210-pack-refs.sh                      |    4 +-
 t/t3403-rebase-skip.sh                    |    8 ++-
 t/t3502-cherry-pick-merge.sh              |   12 +++---
 t/t3600-rm.sh                             |   26 ++++++------
 t/t3700-add.sh                            |    4 +-
 t/t4015-diff-whitespace.sh                |   28 ++++++------
 t/t4018-diff-funcname.sh                  |    2 +-
 t/t4103-apply-binary.sh                   |   16 +++---
 t/t4113-apply-ending.sh                   |    4 +-
 t/t4150-am.sh                             |    8 ++--
 t/t4200-rerere.sh                         |   10 ++--
 t/t5300-pack-object.sh                    |    2 +-
 t/t5302-pack-index.sh                     |   11 +++--
 t/t5401-update-hooks.sh                   |    3 +-
 t/t5404-tracking-branches.sh              |    4 +-
 t/t5406-remote-rejects.sh                 |    2 +-
 t/t5500-fetch-pack.sh                     |    2 +-
 t/t5505-remote.sh                         |   14 +++---
 t/t5510-fetch.sh                          |   12 +++---
 t/t5516-fetch-push.sh                     |    8 ++--
 t/t5530-upload-pack-error.sh              |    6 +-
 t/t5540-http-push.sh                      |    2 +-
 t/t5600-clone-fail-cleanup.sh             |    4 +-
 t/t6023-merge-file.sh                     |   14 +++---
 t/t6024-recursive-merge.sh                |    6 ++-
 t/t6025-merge-symlinks.sh                 |    6 +-
 t/t6101-rev-parse-parents.sh              |    2 +-
 t/t7001-mv.sh                             |    4 +-
 t/t7004-tag.sh                            |   67 +++++++++++++++--------------
 t/t7102-reset.sh                          |   48 ++++++++++----------
 t/t7103-reset-bare.sh                     |    2 +-
 t/t7300-clean.sh                          |    4 +-
 t/t7400-submodule-basic.sh                |    2 +-
 t/t7402-submodule-rebase.sh               |    2 +-
 t/t7500-commit.sh                         |    8 ++--
 t/t7501-commit.sh                         |   18 ++++----
 t/t7503-pre-commit-hook.sh                |    2 +-
 t/t7504-commit-msg-hook.sh                |    2 +-
 t/t7600-merge.sh                          |    2 +-
 t/t7610-mergetool.sh                      |    2 +-
 t/t9100-git-svn-basic.sh                  |   12 +++---
 t/t9106-git-svn-commit-diff-clobber.sh    |    6 +-
 t/t9106-git-svn-dcommit-clobber-series.sh |    2 +-
 t/t9200-git-cvsexportcommit.sh            |    6 +-
 t/t9300-fast-import.sh                    |    8 ++--
 t/t9301-fast-export.sh                    |    4 +-
 57 files changed, 246 insertions(+), 232 deletions(-)

diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index d7cbc5c..70df15c 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -63,7 +63,7 @@ test_expect_failure 'pretend we have fixed a known breakage' '
 
 # updating a new file without --add should fail.
 test_expect_success 'git update-index without --add should fail adding.' '
-    ! git update-index should-be-empty
+    test_must_fail git update-index should-be-empty
 '
 
 # and with --add it should succeed, even if it is empty (it used to fail).
@@ -83,7 +83,7 @@ test_expect_success \
 # Removing paths.
 rm -f should-be-empty full-of-directories
 test_expect_success 'git update-index without --remove should fail removing.' '
-    ! git update-index should-be-empty
+    test_must_fail git update-index should-be-empty
 '
 
 test_expect_success \
@@ -217,7 +217,7 @@ test_expect_success \
     'git update-index --index-info < badobjects'
 
 test_expect_success 'writing this tree without --missing-ok.' '
-    ! git write-tree
+    test_must_fail git write-tree
 '
 
 test_expect_success \
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 2bfeac9..1be7446 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -52,7 +52,7 @@ test_expect_success 'safecrlf: autocrlf=input, all CRLF' '
 	git config core.safecrlf true &&
 
 	for w in I am all CRLF; do echo $w; done | append_cr >allcrlf &&
-	! git add allcrlf
+	test_must_fail git add allcrlf
 '
 
 test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '
@@ -61,7 +61,7 @@ test_expect_success 'safecrlf: autocrlf=input, mixed LF/CRLF' '
 	git config core.safecrlf true &&
 
 	for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
-	! git add mixed
+	test_must_fail git add mixed
 '
 
 test_expect_success 'safecrlf: autocrlf=true, all LF' '
@@ -70,7 +70,7 @@ test_expect_success 'safecrlf: autocrlf=true, all LF' '
 	git config core.safecrlf true &&
 
 	for w in I am all LF; do echo $w; done >alllf &&
-	! git add alllf
+	test_must_fail git add alllf
 '
 
 test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '
@@ -79,7 +79,7 @@ test_expect_success 'safecrlf: autocrlf=true mixed LF/CRLF' '
 	git config core.safecrlf true &&
 
 	for w in Oh here is CRLFQ in text; do echo $w; done | q_to_cr >mixed &&
-	! git add mixed
+	test_must_fail git add mixed
 '
 
 test_expect_success 'safecrlf: print warning only once' '
diff --git a/t/t0050-filesystem.sh b/t/t0050-filesystem.sh
index c5360e2..b177174 100755
--- a/t/t0050-filesystem.sh
+++ b/t/t0050-filesystem.sh
@@ -43,7 +43,7 @@ test_expect_success "detection of case insensitive filesystem during repo init"
 else
 test_expect_success "detection of case insensitive filesystem during repo init" '
 
-	! git config --bool core.ignorecase >/dev/null ||
+	test_must_fail git config --bool core.ignorecase >/dev/null ||
 	test $(git config --bool core.ignorecase) = false
 '
 fi
diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh
index dcb3108..09a8199 100755
--- a/t/t1200-tutorial.sh
+++ b/t/t1200-tutorial.sh
@@ -102,7 +102,7 @@ echo "Lots of fun" >>example
 git commit -m 'Some fun.' -i hello example
 
 test_expect_success 'git resolve now fails' '
-	! git merge -m "Merge work in mybranch" mybranch
+	test_must_fail git merge -m "Merge work in mybranch" mybranch
 '
 
 cat > hello << EOF
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index afe7e66..64567fb 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -201,7 +201,7 @@ test_expect_success 'non-match value' \
 	'test wow = $(git config --get nextsection.nonewline !for)'
 
 test_expect_success 'ambiguous get' '
-	! git config --get nextsection.nonewline
+	test_must_fail git config --get nextsection.nonewline
 '
 
 test_expect_success 'get multivar' \
@@ -223,15 +223,15 @@ EOF
 test_expect_success 'multivar replace' 'cmp .git/config expect'
 
 test_expect_success 'ambiguous value' '
-	! git config nextsection.nonewline
+	test_must_fail git config nextsection.nonewline
 '
 
 test_expect_success 'ambiguous unset' '
-	! git config --unset nextsection.nonewline
+	test_must_fail git config --unset nextsection.nonewline
 '
 
 test_expect_success 'invalid unset' '
-	! git config --unset somesection.nonewline
+	test_must_fail git config --unset somesection.nonewline
 '
 
 git config --unset nextsection.nonewline "wow3$"
@@ -248,7 +248,7 @@ EOF
 
 test_expect_success 'multivar unset' 'cmp .git/config expect'
 
-test_expect_success 'invalid key' '! git config inval.2key blabla'
+test_expect_success 'invalid key' 'test_must_fail git config inval.2key blabla'
 
 test_expect_success 'correct key' 'git config 123456.a123 987'
 
@@ -430,7 +430,8 @@ EOF
 test_expect_success "rename succeeded" "test_cmp expect .git/config"
 
 test_expect_success "rename non-existing section" '
-	! git config --rename-section branch."world domination" branch.drei
+	test_must_fail git config --rename-section \
+		branch."world domination" branch.drei
 '
 
 test_expect_success "rename succeeded" "test_cmp expect .git/config"
@@ -545,11 +546,11 @@ test_expect_success bool '
 test_expect_success 'invalid bool (--get)' '
 
 	git config bool.nobool foobar &&
-	! git config --bool --get bool.nobool'
+	test_must_fail git config --bool --get bool.nobool'
 
 test_expect_success 'invalid bool (set)' '
 
-	! git config --bool bool.nobool foobar'
+	test_must_fail git config --bool bool.nobool foobar'
 
 rm .git/config
 
@@ -669,7 +670,7 @@ EOF
 test_expect_success 'quoting' 'cmp .git/config expect'
 
 test_expect_success 'key with newline' '
-	! git config "key.with
+	test_must_fail git config "key.with
 newline" 123'
 
 test_expect_success 'value with newline' 'git config key.sub value.with\\\
diff --git a/t/t1302-repo-version.sh b/t/t1302-repo-version.sh
index 9be0770..8d305b4 100755
--- a/t/t1302-repo-version.sh
+++ b/t/t1302-repo-version.sh
@@ -41,7 +41,7 @@ test_expect_success 'gitdir required mode on normal repos' '
 	cd test && git apply --check --index ../test.patch)'
 
 test_expect_success 'gitdir required mode on unsupported repo' '
-	(cd test2 && ! git apply --check --index ../test.patch)
+	(cd test2 && test_must_fail git apply --check --index ../test.patch)
 '
 
 test_done
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index ca99d37..b31e4b1 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -76,7 +76,7 @@ test_expect_success "delete $m (by HEAD)" '
 rm -f .git/$m
 
 test_expect_success '(not) create HEAD with old sha1' "
-	! git update-ref HEAD $A $B
+	test_must_fail git update-ref HEAD $A $B
 "
 test_expect_success "(not) prior created .git/$m" "
 	! test -f .git/$m
@@ -87,7 +87,7 @@ test_expect_success \
 	"create HEAD" \
 	"git update-ref HEAD $A"
 test_expect_success '(not) change HEAD with wrong SHA1' "
-	! git update-ref HEAD $B $Z
+	test_must_fail git update-ref HEAD $B $Z
 "
 test_expect_success "(not) changed .git/$m" "
 	! test $B"' = $(cat .git/'"$m"')
diff --git a/t/t2000-checkout-cache-clash.sh b/t/t2000-checkout-cache-clash.sh
index 5141fab..f7e1a73 100755
--- a/t/t2000-checkout-cache-clash.sh
+++ b/t/t2000-checkout-cache-clash.sh
@@ -38,7 +38,7 @@ date >path1
 
 test_expect_success \
     'git checkout-index without -f should fail on conflicting work tree.' \
-    '! git checkout-index -a'
+    'test_must_fail git checkout-index -a'
 
 test_expect_success \
     'git checkout-index with -f should succeed.' \
diff --git a/t/t2100-update-cache-badpath.sh b/t/t2100-update-cache-badpath.sh
index 9beaecd..6ef2dcf 100755
--- a/t/t2100-update-cache-badpath.sh
+++ b/t/t2100-update-cache-badpath.sh
@@ -46,6 +46,6 @@ for p in path0/file0 path1/file1 path2 path3
 do
 	test_expect_success \
 	    "git update-index to add conflicting path $p should fail." \
-	    "! git update-index --add -- $p"
+	    "test_must_fail git update-index --add -- $p"
 done
 test_done
diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh
index f4da869..af8c412 100755
--- a/t/t3020-ls-files-error-unmatch.sh
+++ b/t/t3020-ls-files-error-unmatch.sh
@@ -17,7 +17,7 @@ git-commit -m "add foo bar"
 
 test_expect_success \
     'git ls-files --error-unmatch should fail with unmatched path.' \
-    '! git ls-files --error-unmatch foo bar-does-not-match'
+    'test_must_fail git ls-files --error-unmatch foo bar-does-not-match'
 
 test_expect_success \
     'git ls-files --error-unmatch should succeed eith matched paths.' \
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 8d87686..7c583c8 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -78,13 +78,13 @@ test_expect_success \
 test_expect_success 'git branch -m o/o o should fail when o/p exists' '
 	git branch o/o &&
         git branch o/p &&
-	! git branch -m o/o o
+	test_must_fail git branch -m o/o o
 '
 
 test_expect_success 'git branch -m q r/q should fail when r exists' '
 	git branch q &&
 	git branch r &&
-	! git branch -m q r/q
+	test_must_fail git branch -m q r/q
 '
 
 mv .git/config .git/config-saved
@@ -110,14 +110,14 @@ test_expect_success \
 
 test_expect_success 'config information was renamed, too' \
 	"test $(git config branch.s.dummy) = Hello &&
-	 ! git config branch.s/s/dummy"
+	 test_must_fail git config branch.s/s/dummy"
 
 test_expect_success \
     'git branch -m u v should fail when the reflog for u is a symlink' '
      git branch -l u &&
      mv .git/logs/refs/heads/u real-u &&
      ln -s real-u .git/logs/refs/heads/u &&
-     ! git branch -m u v
+     test_must_fail git branch -m u v
 '
 
 test_expect_success 'test tracking setup via --track' \
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index b64ccfb..c2dec1c 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -43,7 +43,7 @@ test_expect_success 'git branch c/d should barf if branch c exists' '
      git branch c &&
      git pack-refs --all &&
      rm -f .git/refs/heads/c &&
-     ! git branch c/d
+     test_must_fail git branch c/d
 '
 
 test_expect_success \
@@ -72,7 +72,7 @@ test_expect_success \
 test_expect_success 'git branch i/j/k should barf if branch i exists' '
      git branch i &&
      git pack-refs --all --prune &&
-     ! git branch i/j/k
+     test_must_fail git branch i/j/k
 '
 
 test_expect_success \
diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh
index 0a26099..0d33c71 100755
--- a/t/t3403-rebase-skip.sh
+++ b/t/t3403-rebase-skip.sh
@@ -32,7 +32,7 @@ test_expect_success setup '
 	'
 
 test_expect_success 'rebase with git am -3 (default)' '
-	! git rebase master
+	test_must_fail git rebase master
 '
 
 test_expect_success 'rebase --skip with am -3' '
@@ -43,7 +43,7 @@ test_expect_success 'rebase moves back to skip-reference' '
 	test refs/heads/skip-reference = $(git symbolic-ref HEAD) &&
 	git branch post-rebase &&
 	git reset --hard pre-rebase &&
-	! git rebase master &&
+	test_must_fail git rebase master &&
 	echo "hello" > hello &&
 	git add hello &&
 	git rebase --continue &&
@@ -53,7 +53,9 @@ test_expect_success 'rebase moves back to skip-reference' '
 
 test_expect_success 'checkout skip-merge' 'git checkout -f skip-merge'
 
-test_expect_success 'rebase with --merge' '! git rebase --merge master'
+test_expect_success 'rebase with --merge' '
+	test_must_fail git rebase --merge master
+'
 
 test_expect_success 'rebase --skip with --merge' '
 	git rebase --skip
diff --git a/t/t3502-cherry-pick-merge.sh b/t/t3502-cherry-pick-merge.sh
index 7c92e26..0ab52da 100755
--- a/t/t3502-cherry-pick-merge.sh
+++ b/t/t3502-cherry-pick-merge.sh
@@ -35,7 +35,7 @@ test_expect_success 'cherry-pick a non-merge with -m should fail' '
 
 	git reset --hard &&
 	git checkout a^0 &&
-	! git cherry-pick -m 1 b &&
+	test_must_fail git cherry-pick -m 1 b &&
 	git diff --exit-code a --
 
 '
@@ -44,7 +44,7 @@ test_expect_success 'cherry pick a merge without -m should fail' '
 
 	git reset --hard &&
 	git checkout a^0 &&
-	! git cherry-pick c &&
+	test_must_fail git cherry-pick c &&
 	git diff --exit-code a --
 
 '
@@ -71,7 +71,7 @@ test_expect_success 'cherry pick a merge relative to nonexistent parent should f
 
 	git reset --hard &&
 	git checkout b^0 &&
-	! git cherry-pick -m 3 c
+	test_must_fail git cherry-pick -m 3 c
 
 '
 
@@ -79,7 +79,7 @@ test_expect_success 'revert a non-merge with -m should fail' '
 
 	git reset --hard &&
 	git checkout c^0 &&
-	! git revert -m 1 b &&
+	test_must_fail git revert -m 1 b &&
 	git diff --exit-code c
 
 '
@@ -88,7 +88,7 @@ test_expect_success 'revert a merge without -m should fail' '
 
 	git reset --hard &&
 	git checkout c^0 &&
-	! git revert c &&
+	test_must_fail git revert c &&
 	git diff --exit-code c
 
 '
@@ -115,7 +115,7 @@ test_expect_success 'revert a merge relative to nonexistent parent should fail'
 
 	git reset --hard &&
 	git checkout c^0 &&
-	! git revert -m 3 c &&
+	test_must_fail git revert -m 3 c &&
 	git diff --exit-code c
 
 '
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index f542f0a..316775e 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -67,7 +67,7 @@ test_expect_success \
      echo "other content" > foo
      git add foo
      echo "yet another content" > foo
-     ! git rm --cached foo
+     test_must_fail git rm --cached foo
 '
 
 test_expect_success \
@@ -82,7 +82,7 @@ test_expect_success \
 
 test_expect_success \
     'Post-check that foo exists but is not in index after git rm foo' \
-    '[ -f foo ] && ! git ls-files --error-unmatch foo'
+    '[ -f foo ] && test_must_fail git ls-files --error-unmatch foo'
 
 test_expect_success \
     'Pre-check that bar exists and is in index before "git rm bar"' \
@@ -94,7 +94,7 @@ test_expect_success \
 
 test_expect_success \
     'Post-check that bar does not exist and is not in index after "git rm -f bar"' \
-    '! [ -f bar ] && ! git ls-files --error-unmatch bar'
+    '! [ -f bar ] && test_must_fail git ls-files --error-unmatch bar'
 
 test_expect_success \
     'Test that "git rm -- -q" succeeds (remove a file that looks like an option)' \
@@ -109,7 +109,7 @@ if test "$test_failed_remove" = y; then
 chmod a-w .
 test_expect_success \
     'Test that "git rm -f" fails if its rm fails' \
-    '! git rm -f baz'
+    'test_must_fail git rm -f baz'
 chmod 775 .
 else
     test_expect_success 'skipping removal failure (perhaps running as root?)' :
@@ -151,7 +151,7 @@ test_expect_success 'Re-add foo and baz' '
 
 test_expect_success 'Modify foo -- rm should refuse' '
 	echo >>foo &&
-	! git rm foo baz &&
+	test_must_fail git rm foo baz &&
 	test -f foo &&
 	test -f baz &&
 	git ls-files --error-unmatch foo baz
@@ -161,8 +161,8 @@ test_expect_success 'Modified foo -- rm -f should work' '
 	git rm -f foo baz &&
 	test ! -f foo &&
 	test ! -f baz &&
-	! git ls-files --error-unmatch foo &&
-	! git ls-files --error-unmatch bar
+	test_must_fail git ls-files --error-unmatch foo &&
+	test_must_fail git ls-files --error-unmatch bar
 '
 
 test_expect_success 'Re-add foo and baz for HEAD tests' '
@@ -173,7 +173,7 @@ test_expect_success 'Re-add foo and baz for HEAD tests' '
 '
 
 test_expect_success 'foo is different in index from HEAD -- rm should refuse' '
-	! git rm foo baz &&
+	test_must_fail git rm foo baz &&
 	test -f foo &&
 	test -f baz &&
 	git ls-files --error-unmatch foo baz
@@ -183,8 +183,8 @@ test_expect_success 'but with -f it should work.' '
 	git rm -f foo baz &&
 	test ! -f foo &&
 	test ! -f baz &&
-	! git ls-files --error-unmatch foo
-	! git ls-files --error-unmatch baz
+	test_must_fail git ls-files --error-unmatch foo
+	test_must_fail git ls-files --error-unmatch baz
 '
 
 test_expect_success 'Recursive test setup' '
@@ -195,14 +195,14 @@ test_expect_success 'Recursive test setup' '
 '
 
 test_expect_success 'Recursive without -r fails' '
-	! git rm frotz &&
+	test_must_fail git rm frotz &&
 	test -d frotz &&
 	test -f frotz/nitfol
 '
 
 test_expect_success 'Recursive with -r but dirty' '
 	echo qfwfq >>frotz/nitfol
-	! git rm -r frotz &&
+	test_must_fail git rm -r frotz &&
 	test -d frotz &&
 	test -f frotz/nitfol
 '
@@ -214,7 +214,7 @@ test_expect_success 'Recursive with -r -f' '
 '
 
 test_expect_success 'Remove nonexistent file returns nonzero exit status' '
-	! git rm nonexistent
+	test_must_fail git rm nonexistent
 '
 
 test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index e83fa1f..7d123d1 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -85,12 +85,12 @@ test_expect_success '.gitignore is honored' '
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
-	! git add a.?? &&
+	test_must_fail git add a.?? &&
 	! (git ls-files | grep "\\.ig")
 '
 
 test_expect_success 'error out when attempting to add ignored ones without -f' '
-	! git add d.?? &&
+	test_must_fail git add d.?? &&
 	! (git ls-files | grep "\\.ig")
 '
 
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 0922c70..a27fccc 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -144,7 +144,7 @@ test_expect_success 'check with no whitespace errors' '
 test_expect_success 'check with trailing whitespace' '
 
 	echo "foo(); " > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -152,7 +152,7 @@ test_expect_success 'check with space before tab in indent' '
 
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -181,7 +181,7 @@ test_expect_success 'check staged with trailing whitespace' '
 
 	echo "foo(); " > x &&
 	git add x &&
-	! git diff --cached --check
+	test_must_fail git diff --cached --check
 
 '
 
@@ -190,7 +190,7 @@ test_expect_success 'check staged with space before tab in indent' '
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git add x &&
-	! git diff --cached --check
+	test_must_fail git diff --cached --check
 
 '
 
@@ -206,7 +206,7 @@ test_expect_success 'check with trailing whitespace (diff-index)' '
 
 	echo "foo(); " > x &&
 	git add x &&
-	! git diff-index --check HEAD
+	test_must_fail git diff-index --check HEAD
 
 '
 
@@ -215,7 +215,7 @@ test_expect_success 'check with space before tab in indent (diff-index)' '
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git add x &&
-	! git diff-index --check HEAD
+	test_must_fail git diff-index --check HEAD
 
 '
 
@@ -231,7 +231,7 @@ test_expect_success 'check staged with trailing whitespace (diff-index)' '
 
 	echo "foo(); " > x &&
 	git add x &&
-	! git diff-index --cached --check HEAD
+	test_must_fail git diff-index --cached --check HEAD
 
 '
 
@@ -240,7 +240,7 @@ test_expect_success 'check staged with space before tab in indent (diff-index)'
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git add x &&
-	! git diff-index --cached --check HEAD
+	test_must_fail git diff-index --cached --check HEAD
 
 '
 
@@ -256,7 +256,7 @@ test_expect_success 'check with trailing whitespace (diff-tree)' '
 
 	echo "foo(); " > x &&
 	git commit -m "another commit" x &&
-	! git diff-tree --check HEAD^ HEAD
+	test_must_fail git diff-tree --check HEAD^ HEAD
 
 '
 
@@ -265,7 +265,7 @@ test_expect_success 'check with space before tab in indent (diff-tree)' '
 	# indent has space followed by hard tab
 	echo " 	foo();" > x &&
 	git commit -m "yet another" x &&
-	! git diff-tree --check HEAD^ HEAD
+	test_must_fail git diff-tree --check HEAD^ HEAD
 
 '
 
@@ -281,7 +281,7 @@ test_expect_success 'check trailing whitespace (trailing-space: on)' '
 
 	git config core.whitespace "trailing-space" &&
 	echo "foo ();   " > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -299,7 +299,7 @@ test_expect_success 'check space before tab in indent (space-before-tab: on)' '
 	# indent contains space followed by HT
 	git config core.whitespace "space-before-tab" &&
 	echo " 	foo ();   " > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -315,7 +315,7 @@ test_expect_success 'check spaces as indentation (indent-with-non-tab: on)' '
 
 	git config core.whitespace "indent-with-non-tab" &&
 	echo "        foo ();" > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
@@ -323,7 +323,7 @@ test_expect_success 'check tabs and spaces as indentation (indent-with-non-tab:
 
 	git config core.whitespace "indent-with-non-tab" &&
 	echo "	                foo ();" > x &&
-	! git diff --check
+	test_must_fail git diff --check
 
 '
 
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 6d3ef6c..833d6cb 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -54,7 +54,7 @@ test_expect_success 'custom pattern' '
 
 test_expect_success 'last regexp must not be negated' '
 	git config diff.java.funcname "!static" &&
-	! git diff --no-index Beer.java Beer-correct.java
+	test_must_fail git diff --no-index Beer.java Beer-correct.java
 '
 
 test_done
diff --git a/t/t4103-apply-binary.sh b/t/t4103-apply-binary.sh
index 1b58233..7da0b4b 100755
--- a/t/t4103-apply-binary.sh
+++ b/t/t4103-apply-binary.sh
@@ -48,22 +48,22 @@ test_expect_success 'stat binary diff (copy) -- should not fail.' \
 
 test_expect_success 'check binary diff -- should fail.' \
 	'git-checkout master &&
-	 ! git apply --check B.diff'
+	 test_must_fail git apply --check B.diff'
 
 test_expect_success 'check binary diff (copy) -- should fail.' \
 	'git-checkout master &&
-	 ! git apply --check C.diff'
+	 test_must_fail git apply --check C.diff'
 
 test_expect_success \
 	'check incomplete binary diff with replacement -- should fail.' '
 	git-checkout master &&
-	! git apply --check --allow-binary-replacement B.diff
+	test_must_fail git apply --check --allow-binary-replacement B.diff
 '
 
 test_expect_success \
     'check incomplete binary diff with replacement (copy) -- should fail.' '
 	 git-checkout master &&
-	 ! git apply --check --allow-binary-replacement C.diff
+	 test_must_fail git apply --check --allow-binary-replacement C.diff
 '
 
 test_expect_success 'check binary diff with replacement.' \
@@ -84,19 +84,19 @@ do_reset () {
 
 test_expect_success 'apply binary diff -- should fail.' \
 	'do_reset &&
-	 ! git apply B.diff'
+	 test_must_fail git apply B.diff'
 
 test_expect_success 'apply binary diff -- should fail.' \
 	'do_reset &&
-	 ! git apply --index B.diff'
+	 test_must_fail git apply --index B.diff'
 
 test_expect_success 'apply binary diff (copy) -- should fail.' \
 	'do_reset &&
-	 ! git apply C.diff'
+	 test_must_fail git apply C.diff'
 
 test_expect_success 'apply binary diff (copy) -- should fail.' \
 	'do_reset &&
-	 ! git apply --index C.diff'
+	 test_must_fail git apply --index C.diff'
 
 test_expect_success 'apply binary diff without replacement.' \
 	'do_reset &&
diff --git a/t/t4113-apply-ending.sh b/t/t4113-apply-ending.sh
index d741039..66fa515 100755
--- a/t/t4113-apply-ending.sh
+++ b/t/t4113-apply-ending.sh
@@ -30,7 +30,7 @@ test_expect_success setup \
 # test
 
 test_expect_success 'apply at the end' \
-    '! git apply --index test-patch'
+    'test_must_fail git apply --index test-patch'
 
 cat >test-patch <<\EOF
 diff a/file b/file
@@ -48,6 +48,6 @@ c'
 git update-index file
 
 test_expect_success 'apply at the beginning' \
-	'! git apply --index test-patch'
+	'test_must_fail git apply --index test-patch'
 
 test_done
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index bc98260..476f20b 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -182,7 +182,7 @@ test_expect_success 'am -3 falls back to 3-way merge' '
 
 test_expect_success 'am pauses on conflict' '
 	git checkout lorem2^^ &&
-	! git am lorem-move.patch &&
+	test_must_fail git am lorem-move.patch &&
 	test -d .dotest
 '
 
@@ -195,7 +195,7 @@ test_expect_success 'am --skip works' '
 
 test_expect_success 'am --resolved works' '
 	git checkout lorem2^^ &&
-	! git am lorem-move.patch &&
+	test_must_fail git am lorem-move.patch &&
 	test -d .dotest &&
 	echo resolved >>file &&
 	git add file &&
@@ -212,13 +212,13 @@ test_expect_success 'am takes patches from a Pine mailbox' '
 '
 
 test_expect_success 'am fails on mail without patch' '
-	! git am <failmail &&
+	test_must_fail git am <failmail &&
 	rm -r .dotest/
 '
 
 test_expect_success 'am fails on empty patch' '
 	echo "---" >>failmail &&
-	! git am <failmail &&
+	test_must_fail git am <failmail &&
 	git am --skip &&
 	! test -d .dotest
 '
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index a64727d..746d61f 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -41,7 +41,7 @@ git commit -q -a -m second
 
 test_expect_success 'nothing recorded without rerere' '
 	(rm -rf .git/rr-cache; git config rerere.enabled false) &&
-	! git merge first &&
+	test_must_fail git merge first &&
 	! test -d .git/rr-cache
 '
 
@@ -50,7 +50,7 @@ test_expect_success 'conflicting merge' '
 	git reset --hard &&
 	mkdir .git/rr-cache &&
 	git config --unset rerere.enabled &&
-	! git merge first
+	test_must_fail git merge first
 '
 
 sha1=$(sed -e 's/	.*//' .git/rr-cache/MERGE_RR)
@@ -61,7 +61,7 @@ test_expect_success 'rerere.enabled works, too' '
 	rm -rf .git/rr-cache &&
 	git config rerere.enabled true &&
 	git reset --hard &&
-	! git merge first &&
+	test_must_fail git merge first &&
 	grep ======= $rr/preimage
 '
 
@@ -120,7 +120,7 @@ test_expect_success 'another conflicting merge' '
 	git checkout -b third master &&
 	git show second^:a1 | sed "s/To die: t/To die! T/" > a1 &&
 	git commit -q -a -m third &&
-	! git pull . first
+	test_must_fail git pull . first
 '
 
 git show first:a1 | sed 's/To die: t/To die! T/' > expect
@@ -175,7 +175,7 @@ test_expect_success 'file2 added differently in two branches' '
 	echo Bello > file2 &&
 	git add file2 &&
 	git commit -m version2 &&
-	! git merge fourth &&
+	test_must_fail git merge fourth &&
 	sha1=$(sed -e "s/	.*//" .git/rr-cache/MERGE_RR) &&
 	rr=.git/rr-cache/$sha1 &&
 	echo Cello > file2 &&
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index 983a393..645583f 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -266,7 +266,7 @@ test_expect_success \
 
 test_expect_success \
     'make sure index-pack detects the SHA1 collision' \
-    '! git-index-pack -o bad.idx test-3.pack'
+    'test_must_fail git-index-pack -o bad.idx test-3.pack'
 
 test_expect_success \
     'honor pack.packSizeLimit' \
diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh
index ecec591..0639772 100755
--- a/t/t5302-pack-index.sh
+++ b/t/t5302-pack-index.sh
@@ -118,7 +118,7 @@ test_expect_success \
 
 test_expect_success \
     '[index v1] 4) confirm that the pack is actually corrupted' \
-    '! git fsck --full $commit'
+    'test_must_fail git fsck --full $commit'
 
 test_expect_success \
     '[index v1] 5) pack-objects happily reuses corrupted data' \
@@ -127,7 +127,7 @@ test_expect_success \
 
 test_expect_success \
     '[index v1] 6) newly created pack is BAD !' \
-    '! git verify-pack -v "test-4-${pack1}.pack"'
+    'test_must_fail git verify-pack -v "test-4-${pack1}.pack"'
 
 test_expect_success \
     '[index v2] 1) stream pack to repository' \
@@ -156,11 +156,11 @@ test_expect_success \
 
 test_expect_success \
     '[index v2] 4) confirm that the pack is actually corrupted' \
-    '! git fsck --full $commit'
+    'test_must_fail git fsck --full $commit'
 
 test_expect_success \
     '[index v2] 5) pack-objects refuses to reuse corrupted data' \
-    '! git pack-objects test-5 <obj-list'
+    'test_must_fail git pack-objects test-5 <obj-list'
 
 test_expect_success \
     '[index v2] 6) verify-pack detects CRC mismatch' \
@@ -173,7 +173,8 @@ test_expect_success \
      ( while read obj
        do git cat-file -p $obj >/dev/null || exit 1
        done <obj-list ) &&
-     err=$(! git verify-pack ".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
+     err=$(test_must_fail git verify-pack \
+       ".git/objects/pack/pack-${pack1}.pack" 2>&1) &&
      echo "$err" | grep "CRC mismatch"'
 
 test_done
diff --git a/t/t5401-update-hooks.sh b/t/t5401-update-hooks.sh
index 2fff300..ee769d6 100755
--- a/t/t5401-update-hooks.sh
+++ b/t/t5401-update-hooks.sh
@@ -61,7 +61,8 @@ EOF
 chmod u+x victim/.git/hooks/post-update
 
 test_expect_success push '
-    ! git-send-pack --force ./victim/.git master tofail >send.out 2>send.err
+	test_must_fail git-send-pack --force ./victim/.git \
+		master tofail >send.out 2>send.err
 '
 
 test_expect_success 'updated as expected' '
diff --git a/t/t5404-tracking-branches.sh b/t/t5404-tracking-branches.sh
index 64fe261..c240035 100755
--- a/t/t5404-tracking-branches.sh
+++ b/t/t5404-tracking-branches.sh
@@ -35,7 +35,9 @@ test_expect_success 'prepare pushable branches' '
 	git commit -a -m aa-master
 '
 
-test_expect_success 'mixed-success push returns error' '! git push'
+test_expect_success 'mixed-success push returns error' '
+	test_must_fail git push
+'
 
 test_expect_success 'check tracking branches updated correctly after push' '
 	test "$(git rev-parse origin/master)" = "$(git rev-parse master)"
diff --git a/t/t5406-remote-rejects.sh b/t/t5406-remote-rejects.sh
index 46b2cb4..59e80a5 100755
--- a/t/t5406-remote-rejects.sh
+++ b/t/t5406-remote-rejects.sh
@@ -17,7 +17,7 @@ test_expect_success 'setup' '
 	git commit -a -m 2
 '
 
-test_expect_success 'push reports error' '! git push 2>stderr'
+test_expect_success 'push reports error' 'test_must_fail git push 2>stderr'
 
 test_expect_success 'individual ref reports error' 'grep rejected stderr'
 
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 140e874..362cf7e 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -177,6 +177,6 @@ test_expect_success "clone shallow object count" \
 	"test \"count: 18\" = \"$(grep count count.shallow)\""
 
 test_expect_success "pull in shallow repo with missing merge base" \
-	"(cd shallow && ! git pull --depth 4 .. A)"
+	"(cd shallow && test_must_fail git pull --depth 4 .. A)"
 
 test_done
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 1e192a2..be9ee93 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -164,7 +164,7 @@ test_expect_success 'prune' '
 	 git fetch origin &&
 	 git remote prune origin &&
 	 git rev-parse refs/remotes/origin/side2 &&
-	 ! git rev-parse refs/remotes/origin/side)
+	 test_must_fail git rev-parse refs/remotes/origin/side)
 '
 
 cat > test/expect << EOF
@@ -179,7 +179,7 @@ test_expect_success 'prune --dry-run' '
 	(cd test &&
 	 git remote prune --dry-run origin > output &&
 	 git rev-parse refs/remotes/origin/side2 &&
-	 ! git rev-parse refs/remotes/origin/side &&
+	 test_must_fail git rev-parse refs/remotes/origin/side &&
 	(cd ../one &&
 	 git branch -m side side2) &&
 	 test_cmp expect output)
@@ -194,10 +194,10 @@ test_expect_success 'add --mirror && prune' '
 	 git branch -m side2 side) &&
 	(cd mirror &&
 	 git rev-parse --verify refs/heads/side2 &&
-	 ! git rev-parse --verify refs/heads/side &&
+	 test_must_fail git rev-parse --verify refs/heads/side &&
 	 git fetch origin &&
 	 git remote prune origin &&
-	 ! git rev-parse --verify refs/heads/side2 &&
+	 test_must_fail git rev-parse --verify refs/heads/side2 &&
 	 git rev-parse --verify refs/heads/side)
 '
 
@@ -212,10 +212,10 @@ test_expect_success 'add alt && prune' '
 	 git branch -m side side2) &&
 	(cd alttst &&
 	 git rev-parse --verify refs/remotes/origin/side &&
-	 ! git rev-parse --verify refs/remotes/origin/side2 &&
+	 test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
 	 git fetch alt &&
 	 git remote prune alt &&
-	 ! git rev-parse --verify refs/remotes/origin/side &&
+	 test_must_fail git rev-parse --verify refs/remotes/origin/side &&
 	 git rev-parse --verify refs/remotes/origin/side2)
 '
 
@@ -320,7 +320,7 @@ test_expect_success '"remote show" does not show symbolic refs' '
 
 test_expect_success 'reject adding remote with an invalid name' '
 
-	! git remote add some:url desired-name
+	test_must_fail git remote add some:url desired-name
 
 '
 
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index df7750f..13d1d82 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -104,7 +104,7 @@ test_expect_success 'fetch must not resolve short tag name' '
 	cd five &&
 	git init &&
 
-	! git fetch .. anno:five
+	test_must_fail git fetch .. anno:five
 
 '
 
@@ -117,7 +117,7 @@ test_expect_success 'fetch must not resolve short remote name' '
 	cd six &&
 	git init &&
 
-	! git fetch .. six:six
+	test_must_fail git fetch .. six:six
 
 '
 
@@ -143,7 +143,7 @@ test_expect_success 'create bundle 2' '
 test_expect_success 'unbundle 1' '
 	cd "$D/bundle" &&
 	git checkout -b some-branch &&
-	! git fetch "$D/bundle1" master:master
+	test_must_fail git fetch "$D/bundle1" master:master
 '
 
 test_expect_success 'bundle 1 has only 3 files ' '
@@ -236,7 +236,7 @@ test_expect_success 'fetch with a non-applying branch.<name>.merge' '
 
 # the strange name is: a\!'b
 test_expect_success 'quoting of a strangely named repo' '
-	! git fetch "a\\!'\''b" > result 2>&1 &&
+	test_must_fail git fetch "a\\!'\''b" > result 2>&1 &&
 	cat result &&
 	grep "fatal: '\''a\\\\!'\''b'\''" result
 '
@@ -264,7 +264,7 @@ test_expect_success 'explicit fetch should not update tracking' '
 		git fetch origin master &&
 		n=$(git rev-parse --verify refs/remotes/origin/master) &&
 		test "$o" = "$n" &&
-		! git rev-parse --verify refs/remotes/origin/side
+		test_must_fail git rev-parse --verify refs/remotes/origin/side
 	)
 '
 
@@ -278,7 +278,7 @@ test_expect_success 'explicit pull should not update tracking' '
 		git pull origin master &&
 		n=$(git rev-parse --verify refs/remotes/origin/master) &&
 		test "$o" = "$n" &&
-		! git rev-parse --verify refs/remotes/origin/side
+		test_must_fail git rev-parse --verify refs/remotes/origin/side
 	)
 '
 
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 6805032..f0030ad 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -178,7 +178,7 @@ test_expect_success 'failed (non-fast-forward) push with matching heads' '
 	mk_test heads/master &&
 	git push testrepo : &&
 	git commit --amend -massaged &&
-	! git push testrepo &&
+	test_must_fail git push testrepo &&
 	check_push_result $the_commit heads/master &&
 	git reset --hard $the_commit
 
@@ -374,7 +374,7 @@ test_expect_success 'push with +HEAD' '
 
 	# Without force rewinding should fail
 	git reset --hard HEAD^ &&
-	! git push testrepo HEAD &&
+	test_must_fail git push testrepo HEAD &&
 	check_push_result $the_commit heads/local &&
 
 	# With force rewinding should succeed
@@ -448,7 +448,7 @@ test_expect_success 'push does not update local refs on failure' '
 	git clone parent child &&
 	(cd child &&
 		echo two >foo && git commit -a -m two &&
-		! git push &&
+		test_must_fail git push &&
 		test $(git rev-parse master) != \
 			$(git rev-parse remotes/origin/master))
 
@@ -459,7 +459,7 @@ test_expect_success 'allow deleting an invalid remote ref' '
 	pwd &&
 	rm -f testrepo/.git/objects/??/* &&
 	git push testrepo :refs/heads/master &&
-	(cd testrepo && ! git rev-parse --verify refs/heads/master)
+	(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)
 
 '
 
diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh
index 8b05091..1a15817 100755
--- a/t/t5530-upload-pack-error.sh
+++ b/t/t5530-upload-pack-error.sh
@@ -27,7 +27,7 @@ test_expect_success 'setup and corrupt repository' '
 '
 
 test_expect_success 'fsck fails' '
-	! git fsck
+	test_must_fail git fsck
 '
 
 test_expect_success 'upload-pack fails due to error in pack-objects' '
@@ -46,7 +46,7 @@ test_expect_success 'corrupt repo differently' '
 '
 
 test_expect_success 'fsck fails' '
-	! git fsck
+	test_must_fail git fsck
 '
 test_expect_success 'upload-pack fails due to error in rev-list' '
 
@@ -66,7 +66,7 @@ test_expect_success 'create empty repository' '
 
 test_expect_success 'fetch fails' '
 
-	! git fetch .. master
+	test_must_fail git fetch .. master
 
 '
 
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
index 21dbb55..f8c17cd 100755
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
@@ -73,7 +73,7 @@ test_expect_failure 'create and delete remote branch' '
 	git push origin :dev &&
 	git branch -d -r origin/dev &&
 	git fetch &&
-	! git show-ref --verify refs/remotes/origin/dev
+	test_must_fail git show-ref --verify refs/remotes/origin/dev
 '
 
 stop_httpd
diff --git a/t/t5600-clone-fail-cleanup.sh b/t/t5600-clone-fail-cleanup.sh
index acf34ce..3c013e2 100755
--- a/t/t5600-clone-fail-cleanup.sh
+++ b/t/t5600-clone-fail-cleanup.sh
@@ -13,7 +13,7 @@ remove the directory before attempting a clone again.'
 
 test_expect_success \
     'clone of non-existent source should fail' \
-    '! git-clone foo bar'
+    'test_must_fail git-clone foo bar'
 
 test_expect_success \
     'failed clone should not leave a directory' \
@@ -29,7 +29,7 @@ test_create_repo foo
 # current path not to the target dir
 test_expect_success \
     'clone of non-existent (relative to $PWD) source should fail' \
-    '! git-clone ../foo baz'
+    'test_must_fail git-clone ../foo baz'
 
 test_expect_success \
     'clone should work now that source exists' \
diff --git a/t/t6023-merge-file.sh b/t/t6023-merge-file.sh
index 74e9e66..f674c48 100755
--- a/t/t6023-merge-file.sh
+++ b/t/t6023-merge-file.sh
@@ -67,7 +67,7 @@ test_expect_success "merge result added missing LF" \
 
 cp test.txt backup.txt
 test_expect_success "merge with conflicts" \
-	"! git merge-file test.txt orig.txt new3.txt"
+	"test_must_fail git merge-file test.txt orig.txt new3.txt"
 
 cat > expect.txt << EOF
 <<<<<<< test.txt
@@ -90,7 +90,7 @@ test_expect_success "expected conflict markers" "test_cmp test.txt expect.txt"
 
 cp backup.txt test.txt
 test_expect_success "merge with conflicts, using -L" \
-	"! git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
+	"test_must_fail git merge-file -L 1 -L 2 test.txt orig.txt new3.txt"
 
 cat > expect.txt << EOF
 <<<<<<< 1
@@ -114,7 +114,7 @@ test_expect_success "expected conflict markers, with -L" \
 
 sed "s/ tu / TU /" < new1.txt > new5.txt
 test_expect_success "conflict in removed tail" \
-	"! git merge-file -p orig.txt new1.txt new5.txt > out"
+	"test_must_fail git merge-file -p orig.txt new1.txt new5.txt > out"
 
 cat > expect << EOF
 Dominus regit me,
@@ -135,7 +135,8 @@ EOF
 test_expect_success "expected conflict markers" "test_cmp expect out"
 
 test_expect_success 'binary files cannot be merged' '
-	! git merge-file -p orig.txt ../test4012.png new1.txt 2> merge.err &&
+	test_must_fail git merge-file -p \
+		orig.txt ../test4012.png new1.txt 2> merge.err &&
 	grep "Cannot merge binary files" merge.err
 '
 
@@ -144,7 +145,7 @@ sed -e "s/deerit.$/deerit,/" -e "s/me;$/me,/" < new5.txt > new7.txt
 
 test_expect_success 'MERGE_ZEALOUS simplifies non-conflicts' '
 
-	! git merge-file -p new6.txt new5.txt new7.txt > output &&
+	test_must_fail git merge-file -p new6.txt new5.txt new7.txt > output &&
 	test 1 = $(grep ======= < output | wc -l)
 
 '
@@ -154,7 +155,8 @@ sed -e 's/deerit./&\n\n\n\n/' -e "s/locavit,/locavit --/" < new7.txt > new9.txt
 
 test_expect_success 'ZEALOUS_ALNUM' '
 
-	! git merge-file -p new8.txt new5.txt new9.txt > merge.out &&
+	test_must_fail git merge-file -p \
+		new8.txt new5.txt new9.txt > merge.out &&
 	test 1 = $(grep ======= < merge.out | wc -l)
 
 '
diff --git a/t/t6024-recursive-merge.sh b/t/t6024-recursive-merge.sh
index 6a6a130..802d0d0 100755
--- a/t/t6024-recursive-merge.sh
+++ b/t/t6024-recursive-merge.sh
@@ -60,7 +60,9 @@ git update-index a1 &&
 GIT_AUTHOR_DATE="2006-12-12 23:00:08" git commit -m F
 '
 
-test_expect_success "combined merge conflicts" "! git merge -m final G"
+test_expect_success "combined merge conflicts" "
+	test_must_fail git merge -m final G
+"
 
 cat > expect << EOF
 <<<<<<< HEAD:a1
@@ -90,7 +92,7 @@ test_expect_success 'refuse to merge binary files' '
 	printf "\0\0" > binary-file &&
 	git add binary-file &&
 	git commit -m binary2 &&
-	! git merge F > merge.out 2> merge.err &&
+	test_must_fail git merge F > merge.out 2> merge.err &&
 	grep "Cannot merge binary files: HEAD:binary-file vs. F:binary-file" \
 		merge.err
 '
diff --git a/t/t6025-merge-symlinks.sh b/t/t6025-merge-symlinks.sh
index 6004deb..fc58456 100755
--- a/t/t6025-merge-symlinks.sh
+++ b/t/t6025-merge-symlinks.sh
@@ -33,7 +33,7 @@ git-commit -m b-file'
 test_expect_success \
 'merge master into b-symlink, which has a different symbolic link' '
 git-checkout b-symlink &&
-! git-merge master'
+test_must_fail git-merge master'
 
 test_expect_success \
 'the merge result must be a file' '
@@ -42,7 +42,7 @@ test -f symlink'
 test_expect_success \
 'merge master into b-file, which has a file instead of a symbolic link' '
 git-reset --hard && git-checkout b-file &&
-! git-merge master'
+test_must_fail git-merge master'
 
 test_expect_success \
 'the merge result must be a file' '
@@ -52,7 +52,7 @@ test_expect_success \
 'merge b-file, which has a file instead of a symbolic link, into master' '
 git-reset --hard &&
 git-checkout master &&
-! git-merge b-file'
+test_must_fail git-merge b-file'
 
 test_expect_success \
 'the merge result must be a file' '
diff --git a/t/t6101-rev-parse-parents.sh b/t/t6101-rev-parse-parents.sh
index 2328b69..efc8313 100755
--- a/t/t6101-rev-parse-parents.sh
+++ b/t/t6101-rev-parse-parents.sh
@@ -26,7 +26,7 @@ test_expect_success 'final^1^1^1 = final^^^' "test $(git rev-parse final^1^1^1)
 test_expect_success 'final^1^2' "test $(git rev-parse start2) = $(git rev-parse final^1^2)"
 test_expect_success 'final^1^2 != final^1^1' "test $(git rev-parse final^1^2) != $(git rev-parse final^1^1)"
 test_expect_success 'final^1^3 not valid' "if git rev-parse --verify final^1^3; then false; else :; fi"
-test_expect_success '--verify start2^1' '! git rev-parse --verify start2^1'
+test_expect_success '--verify start2^1' 'test_must_fail git rev-parse --verify start2^1'
 test_expect_success '--verify start2^0' 'git rev-parse --verify start2^0'
 
 test_expect_success 'repack for next test' 'git repack -a -d'
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index fa382c5..336cfaa 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -80,7 +80,7 @@ test_expect_success \
 
 test_expect_success \
     'do not move directory over existing directory' \
-    'mkdir path0 && mkdir path0/path2 && ! git mv path2 path0'
+    'mkdir path0 && mkdir path0/path2 && test_must_fail git mv path2 path0'
 
 test_expect_success \
     'move into "."' \
@@ -149,7 +149,7 @@ test_expect_success 'absolute pathname outside should fail' '(
 	>sub/file &&
 	git add sub/file &&
 
-	! git mv sub "$out/out" &&
+	test_must_fail git mv sub "$out/out" &&
 	test -d sub &&
 	! test -d ../in &&
 	git ls-files --error-unmatch sub/file
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 241c70d..bc7ce2c 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -30,17 +30,17 @@ test_expect_success 'looking for a tag in an empty tree should fail' \
 	'! (tag_exists mytag)'
 
 test_expect_success 'creating a tag in an empty tree should fail' '
-	! git-tag mynotag &&
+	test_must_fail git-tag mynotag &&
 	! tag_exists mynotag
 '
 
 test_expect_success 'creating a tag for HEAD in an empty tree should fail' '
-	! git-tag mytaghead HEAD &&
+	test_must_fail git-tag mytaghead HEAD &&
 	! tag_exists mytaghead
 '
 
 test_expect_success 'creating a tag for an unknown revision should fail' '
-	! git-tag mytagnorev aaaaaaaaaaa &&
+	test_must_fail git-tag mytagnorev aaaaaaaaaaa &&
 	! tag_exists mytagnorev
 '
 
@@ -85,16 +85,16 @@ test_expect_success \
 
 test_expect_success \
 	'trying to create a tag with the name of one existing should fail' \
-	'! git tag mytag'
+	'test_must_fail git tag mytag'
 
 test_expect_success \
 	'trying to create a tag with a non-valid name should fail' '
 	test `git-tag -l | wc -l` -eq 1 &&
-	! git tag "" &&
-	! git tag .othertag &&
-	! git tag "other tag" &&
-	! git tag "othertag^" &&
-	! git tag "other~tag" &&
+	test_must_fail git tag "" &&
+	test_must_fail git tag .othertag &&
+	test_must_fail git tag "other tag" &&
+	test_must_fail git tag "othertag^" &&
+	test_must_fail git tag "other~tag" &&
 	test `git-tag -l | wc -l` -eq 1
 '
 
@@ -107,7 +107,7 @@ test_expect_success 'creating a tag using HEAD directly should succeed' '
 
 test_expect_success 'trying to delete an unknown tag should fail' '
 	! tag_exists unknown-tag &&
-	! git-tag -d unknown-tag
+	test_must_fail git-tag -d unknown-tag
 '
 
 cat >expect <<EOF
@@ -141,13 +141,13 @@ test_expect_success \
 	'trying to delete two tags, existing and not, should fail in the 2nd' '
 	tag_exists mytag &&
 	! tag_exists myhead &&
-	! git-tag -d mytag anothertag &&
+	test_must_fail git-tag -d mytag anothertag &&
 	! tag_exists mytag &&
 	! tag_exists myhead
 '
 
 test_expect_success 'trying to delete an already deleted tag should fail' \
-	'! git-tag -d mytag'
+	'test_must_fail git-tag -d mytag'
 
 # listing various tags with pattern matching:
 
@@ -266,15 +266,15 @@ test_expect_success \
 '
 
 test_expect_success 'trying to verify an unknown tag should fail' \
-	'! git-tag -v unknown-tag'
+	'test_must_fail git-tag -v unknown-tag'
 
 test_expect_success \
 	'trying to verify a non-annotated and non-signed tag should fail' \
-	'! git-tag -v non-annotated-tag'
+	'test_must_fail git-tag -v non-annotated-tag'
 
 test_expect_success \
 	'trying to verify many non-annotated or unknown tags, should fail' \
-	'! git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'
+	'test_must_fail git-tag -v unknown-tag1 non-annotated-tag unknown-tag2'
 
 # creating annotated tags:
 
@@ -334,7 +334,7 @@ test_expect_success \
 	'trying to create a tag with a non-existing -F file should fail' '
 	! test -f nonexistingfile &&
 	! tag_exists notag &&
-	! git-tag -F nonexistingfile notag &&
+	test_must_fail git-tag -F nonexistingfile notag &&
 	! tag_exists notag
 '
 
@@ -343,11 +343,12 @@ test_expect_success \
 	echo "message file 1" >msgfile1 &&
 	echo "message file 2" >msgfile2 &&
 	! tag_exists msgtag &&
-	! git-tag -m "message 1" -F msgfile1 msgtag &&
+	test_must_fail git-tag -m "message 1" -F msgfile1 msgtag &&
 	! tag_exists msgtag &&
-	! git-tag -F msgfile1 -m "message 1" msgtag &&
+	test_must_fail git-tag -F msgfile1 -m "message 1" msgtag &&
 	! tag_exists msgtag &&
-	! git-tag -m "message 1" -F msgfile1 -m "message 2" msgtag &&
+	test_must_fail git-tag -m "message 1" -F msgfile1 \
+		-m "message 2" msgtag &&
 	! tag_exists msgtag
 '
 
@@ -591,19 +592,19 @@ fi
 test_expect_success \
 	'trying to verify an annotated non-signed tag should fail' '
 	tag_exists annotated-tag &&
-	! git-tag -v annotated-tag
+	test_must_fail git-tag -v annotated-tag
 '
 
 test_expect_success \
 	'trying to verify a file-annotated non-signed tag should fail' '
 	tag_exists file-annotated-tag &&
-	! git-tag -v file-annotated-tag
+	test_must_fail git-tag -v file-annotated-tag
 '
 
 test_expect_success \
 	'trying to verify two annotated non-signed tags should fail' '
 	tag_exists annotated-tag file-annotated-tag &&
-	! git-tag -v annotated-tag file-annotated-tag
+	test_must_fail git-tag -v annotated-tag file-annotated-tag
 '
 
 # creating and verifying signed tags:
@@ -651,13 +652,14 @@ test_expect_success 'sign with a given key id' '
 
 test_expect_success 'sign with an unknown id (1)' '
 
-	! git tag -u author@example.com -m "Another message" o-signed-tag
+	test_must_fail git tag -u author@example.com \
+		-m "Another message" o-signed-tag
 
 '
 
 test_expect_success 'sign with an unknown id (2)' '
 
-	! git tag -u DEADBEEF -m "Another message" o-signed-tag
+	test_must_fail git tag -u DEADBEEF -m "Another message" o-signed-tag
 
 '
 
@@ -718,7 +720,7 @@ test_expect_success \
 	'trying to create a signed tag with non-existing -F file should fail' '
 	! test -f nonexistingfile &&
 	! tag_exists nosigtag &&
-	! git-tag -s -F nonexistingfile nosigtag &&
+	test_must_fail git-tag -s -F nonexistingfile nosigtag &&
 	! tag_exists nosigtag
 '
 
@@ -730,10 +732,11 @@ test_expect_success 'verifying two signed tags in one command should succeed' \
 
 test_expect_success \
 	'verifying many signed and non-signed tags should fail' '
-	! git-tag -v signed-tag annotated-tag &&
-	! git-tag -v file-annotated-tag file-signed-tag &&
-	! git-tag -v annotated-tag file-signed-tag file-annotated-tag &&
-	! git-tag -v signed-tag annotated-tag file-signed-tag
+	test_must_fail git-tag -v signed-tag annotated-tag &&
+	test_must_fail git-tag -v file-annotated-tag file-signed-tag &&
+	test_must_fail git-tag -v annotated-tag \
+		file-signed-tag file-annotated-tag &&
+	test_must_fail git-tag -v signed-tag annotated-tag file-signed-tag
 '
 
 test_expect_success 'verifying a forged tag should fail' '
@@ -741,7 +744,7 @@ test_expect_success 'verifying a forged tag should fail' '
 		sed -e "s/signed-tag/forged-tag/" |
 		git mktag) &&
 	git tag forged-tag $forged &&
-	! git-tag -v forged-tag
+	test_must_fail git-tag -v forged-tag
 '
 
 # blank and empty messages for signed tags:
@@ -1031,7 +1034,7 @@ test_expect_success \
 git config user.signingkey BobTheMouse
 test_expect_success \
 	'git-tag -s fails if gpg is misconfigured' \
-	'! git tag -s -m tail tag-gpg-failure'
+	'test_must_fail git tag -s -m tail tag-gpg-failure'
 git config --unset user.signingkey
 
 # try to verify without gpg:
@@ -1039,7 +1042,7 @@ git config --unset user.signingkey
 rm -rf gpghome
 test_expect_success \
 	'verify signed tag fails when public key is not present' \
-	'! git-tag -v signed-tag'
+	'test_must_fail git-tag -v signed-tag'
 
 test_expect_success \
 	'git-tag -a fails if tag annotation is empty' '
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 96d1508..0bfc1e9 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -52,10 +52,10 @@ secondfile:
 EOF
 
 test_expect_success 'giving a non existing revision should fail' '
-	! git reset aaaaaa &&
-	! git reset --mixed aaaaaa &&
-	! git reset --soft aaaaaa &&
-	! git reset --hard aaaaaa &&
+	test_must_fail git reset aaaaaa &&
+	test_must_fail git reset --mixed aaaaaa &&
+	test_must_fail git reset --soft aaaaaa &&
+	test_must_fail git reset --hard aaaaaa &&
 	check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
@@ -63,29 +63,29 @@ test_expect_success 'reset --soft with unmerged index should fail' '
 	touch .git/MERGE_HEAD &&
 	echo "100644 44c5b5884550c17758737edcced463447b91d42b 1	un" |
 		git update-index --index-info &&
-	! git reset --soft HEAD &&
+	test_must_fail git reset --soft HEAD &&
 	rm .git/MERGE_HEAD &&
 	git rm --cached -- un
 '
 
 test_expect_success \
 	'giving paths with options different than --mixed should fail' '
-	! git reset --soft -- first &&
-	! git reset --hard -- first &&
-	! git reset --soft HEAD^ -- first &&
-	! git reset --hard HEAD^ -- first &&
+	test_must_fail git reset --soft -- first &&
+	test_must_fail git reset --hard -- first &&
+	test_must_fail git reset --soft HEAD^ -- first &&
+	test_must_fail git reset --hard HEAD^ -- first &&
 	check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
 test_expect_success 'giving unrecognized options should fail' '
-	! git reset --other &&
-	! git reset -o &&
-	! git reset --mixed --other &&
-	! git reset --mixed -o &&
-	! git reset --soft --other &&
-	! git reset --soft -o &&
-	! git reset --hard --other &&
-	! git reset --hard -o &&
+	test_must_fail git reset --other &&
+	test_must_fail git reset -o &&
+	test_must_fail git reset --mixed --other &&
+	test_must_fail git reset --mixed -o &&
+	test_must_fail git reset --soft --other &&
+	test_must_fail git reset --soft -o &&
+	test_must_fail git reset --hard --other &&
+	test_must_fail git reset --hard -o &&
 	check_changes 3ec39651e7f44ea531a5de18a9fa791c0fd370fc
 '
 
@@ -102,8 +102,8 @@ test_expect_success \
 	echo "3rd line in branch2" >>secondfile &&
 	git commit -a -m "change in branch2" &&
 
-	! git merge branch1 &&
-	! git reset --soft &&
+	test_must_fail git merge branch1 &&
+	test_must_fail git reset --soft &&
 
 	printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
 	git commit -a -m "the change in branch2" &&
@@ -126,7 +126,7 @@ test_expect_success \
 	echo "3rd line in branch4" >>secondfile &&
 
 	git checkout -m branch3 &&
-	! git reset --soft &&
+	test_must_fail git reset --soft &&
 
 	printf "1st line 2nd file\n2nd line 2nd file\n3rd line" >secondfile &&
 	git commit -a -m "the line in branch3" &&
@@ -326,7 +326,7 @@ test_expect_success '--hard reset to HEAD should clear a failed merge' '
 	echo "3rd line in branch2" >>secondfile &&
 	git commit -a -m "change in branch2" &&
 
-	! git pull . branch1 &&
+	test_must_fail git pull . branch1 &&
 	git reset --hard &&
 	check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb
 '
@@ -388,7 +388,7 @@ test_expect_success 'test --mixed <paths>' '
 	echo 4 > file4 &&
 	echo 5 > file1 &&
 	git add file1 file3 file4 &&
-	! git reset HEAD -- file1 file2 file3 &&
+	test_must_fail git reset HEAD -- file1 file2 file3 &&
 	git diff > output &&
 	test_cmp output expect &&
 	git diff --cached > output &&
@@ -402,11 +402,11 @@ test_expect_success 'test resetting the index at give paths' '
 	>sub/file2 &&
 	git update-index --add sub/file1 sub/file2 &&
 	T=$(git write-tree) &&
-	! git reset HEAD sub/file2 &&
+	test_must_fail git reset HEAD sub/file2 &&
 	U=$(git write-tree) &&
 	echo "$T" &&
 	echo "$U" &&
-	! git diff-index --cached --exit-code "$T" &&
+	test_must_fail git diff-index --cached --exit-code "$T" &&
 	test "$T" != "$U"
 
 '
diff --git a/t/t7103-reset-bare.sh b/t/t7103-reset-bare.sh
index b25a77f..cdecebe 100755
--- a/t/t7103-reset-bare.sh
+++ b/t/t7103-reset-bare.sh
@@ -17,7 +17,7 @@ test_expect_success 'setup bare' '
 '
 
 test_expect_success 'hard reset is not allowed' '
-	! git reset --hard HEAD^
+	test_must_fail  git reset --hard HEAD^
 '
 
 test_expect_success 'soft reset is allowed' '
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index bd77239..2b51c0d 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -316,14 +316,14 @@ test_expect_success 'git-clean -d -X' '
 test_expect_success 'clean.requireForce defaults to true' '
 
 	git config --unset clean.requireForce &&
-	! git-clean
+	test_must_fail git clean
 
 '
 
 test_expect_success 'clean.requireForce' '
 
 	git config clean.requireForce true &&
-	! git-clean
+	test_must_fail git clean
 
 '
 
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 6c7b902..cbc0c34 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -75,7 +75,7 @@ test_expect_success 'init should register submodule url in .git/config' '
 	then
 		echo "[OOPS] init succeeded but submodule url is wrong"
 		false
-	elif ! git config submodule.example.url ./.subrepo
+	elif test_must_fail git config submodule.example.url ./.subrepo
 	then
 		echo "[OOPS] init succeeded but update of url failed"
 		false
diff --git a/t/t7402-submodule-rebase.sh b/t/t7402-submodule-rebase.sh
index 5becb3e..f919c8d 100755
--- a/t/t7402-submodule-rebase.sh
+++ b/t/t7402-submodule-rebase.sh
@@ -71,7 +71,7 @@ test_expect_success 'rebase with dirty file and submodule fails' '
 	test_tick &&
 	git commit -m rewrite file &&
 	echo dirty > file &&
-	! git rebase --onto HEAD~2 HEAD^
+	test_must_fail git rebase --onto HEAD~2 HEAD^
 
 '
 
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index baed6ce..d89f91a 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -23,12 +23,12 @@ test_expect_success 'a basic commit in an empty tree should succeed' '
 test_expect_success 'nonexistent template file should return error' '
 	echo changes >> foo &&
 	git add foo &&
-	! git commit --template "$PWD"/notexist
+	test_must_fail git commit --template "$PWD"/notexist
 '
 
 test_expect_success 'nonexistent template file in config should return error' '
 	git config commit.template "$PWD"/notexist &&
-	! git commit &&
+	test_must_fail git commit &&
 	git config --unset commit.template
 '
 
@@ -37,12 +37,12 @@ TEMPLATE="$PWD"/template
 
 test_expect_success 'unedited template should not commit' '
 	echo "template line" > "$TEMPLATE" &&
-	! git commit --template "$TEMPLATE"
+	test_must_fail git commit --template "$TEMPLATE"
 '
 
 test_expect_success 'unedited template with comments should not commit' '
 	echo "# comment in template" >> "$TEMPLATE" &&
-	! git commit --template "$TEMPLATE"
+	test_must_fail git commit --template "$TEMPLATE"
 '
 
 test_expect_success 'a Signed-off-by line by itself should not commit' '
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index d3370ff..0edd9dd 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -19,7 +19,7 @@ test_expect_success \
 
 test_expect_success \
 	"fail initial amend" \
-	"! git-commit --amend"
+	"test_must_fail git-commit --amend"
 
 test_expect_success \
 	"initial commit" \
@@ -27,16 +27,16 @@ test_expect_success \
 
 test_expect_success \
 	"invalid options 1" \
-	"! git-commit -m foo -m bar -F file"
+	"test_must_fail git-commit -m foo -m bar -F file"
 
 test_expect_success \
 	"invalid options 2" \
-	"! git-commit -C HEAD -m illegal"
+	"test_must_fail git-commit -C HEAD -m illegal"
 
 test_expect_success \
 	"using paths with -a" \
 	"echo King of the bongo >file &&
-	! git-commit -m foo -a file"
+	test_must_fail git-commit -m foo -a file"
 
 test_expect_success \
 	"using paths with --interactive" \
@@ -45,11 +45,11 @@ test_expect_success \
 
 test_expect_success \
 	"using invalid commit with -C" \
-	"! git-commit -C bogus"
+	"test_must_fail git-commit -C bogus"
 
 test_expect_success \
 	"testing nothing to commit" \
-	"! git-commit -m initial"
+	"test_must_fail git-commit -m initial"
 
 test_expect_success \
 	"next commit" \
@@ -59,7 +59,7 @@ test_expect_success \
 test_expect_success \
 	"commit message from non-existing file" \
 	"echo 'more bongo: bongo bongo bongo bongo' >file && \
-	 ! git-commit -F gah -a"
+	 test_must_fail git-commit -F gah -a"
 
 # Empty except stray tabs and spaces on a few lines.
 sed -e 's/@$//' >msg <<EOF
@@ -70,7 +70,7 @@ Signed-off-by: hula
 EOF
 test_expect_success \
 	"empty commit message" \
-	"! git-commit -F msg -a"
+	"test_must_fail git-commit -F msg -a"
 
 test_expect_success \
 	"commit message from file" \
@@ -91,7 +91,7 @@ test_expect_success \
 test_expect_success \
 	"passing -m and -F" \
 	"echo 'enough with the bongos' >file && \
-	 ! git-commit -F msg -m amending ."
+	 test_must_fail git-commit -F msg -m amending ."
 
 test_expect_success \
 	"using message from other commit" \
diff --git a/t/t7503-pre-commit-hook.sh b/t/t7503-pre-commit-hook.sh
index 2dd5a5e..b069095 100755
--- a/t/t7503-pre-commit-hook.sh
+++ b/t/t7503-pre-commit-hook.sh
@@ -56,7 +56,7 @@ test_expect_success 'with failing hook' '
 
 	echo "another" >> file &&
 	git add file &&
-	! git commit -m "another"
+	test_must_fail git commit -m "another"
 
 '
 
diff --git a/t/t7504-commit-msg-hook.sh b/t/t7504-commit-msg-hook.sh
index 88577af..47680e6 100755
--- a/t/t7504-commit-msg-hook.sh
+++ b/t/t7504-commit-msg-hook.sh
@@ -105,7 +105,7 @@ test_expect_success 'with failing hook' '
 
 	echo "another" >> file &&
 	git add file &&
-	! git commit -m "another"
+	test_must_fail git commit -m "another"
 
 '
 
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index d21cd29..7d182b5 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -126,7 +126,7 @@ verify_merge() {
 		echo "[OOPS] unmerged files"
 		false
 	fi &&
-	if ! git diff --exit-code
+	if test_must_fail git diff --exit-code
 	then
 		echo "[OOPS] working tree != index"
 		false
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index 6b0483f..9285071 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -35,7 +35,7 @@ test_expect_success 'custom mergetool' '
     git config mergetool.mytool.cmd "cat \"\$REMOTE\" >\"\$MERGED\"" &&
     git config mergetool.mytool.trustExitCode true &&
 	git checkout branch1 &&
-    ! git merge master >/dev/null 2>&1 &&
+    test_must_fail git merge master >/dev/null 2>&1 &&
     ( yes "" | git mergetool file1>/dev/null 2>&1 ) &&
     ( yes "" | git mergetool file2>/dev/null 2>&1 ) &&
     test "$(cat file1)" = "master updated" &&
diff --git a/t/t9100-git-svn-basic.sh b/t/t9100-git-svn-basic.sh
index 3bc6164..843a501 100755
--- a/t/t9100-git-svn-basic.sh
+++ b/t/t9100-git-svn-basic.sh
@@ -63,7 +63,7 @@ test_expect_success "$name" "
 	git update-index --remove dir/file &&
 	git update-index --add dir/file/file &&
 	git commit -m '$name' &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch" || true
 
 
@@ -77,7 +77,7 @@ test_expect_success "$name" '
 	git update-index --remove -- bar/zzz &&
 	git update-index --add -- bar &&
 	git commit -m "$name" &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch2' || true
 
 
@@ -91,7 +91,7 @@ test_expect_success "$name" '
 	echo yyy > bar/zzz/yyy &&
 	git update-index --add bar/zzz/yyy &&
 	git commit -m "$name" &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch3' || true
 
 
@@ -105,7 +105,7 @@ test_expect_success "$name" '
 	echo asdf > dir &&
 	git update-index --add -- dir &&
 	git commit -m "$name" &&
-	! git-svn set-tree --find-copies-harder --rmdir \
+	test_must_fail git-svn set-tree --find-copies-harder --rmdir \
 		remotes/git-svn..mybranch4' || true
 
 
@@ -216,7 +216,7 @@ test_expect_success "$name" "test_cmp a expected"
 test_expect_success 'exit if remote refs are ambigious' "
         git config --add svn-remote.svn.fetch \
                               bar:refs/remotes/git-svn &&
-	! git-svn migrate
+	test_must_fail git-svn migrate
 "
 
 test_expect_success 'exit if init-ing a would clobber a URL' '
@@ -224,7 +224,7 @@ test_expect_success 'exit if init-ing a would clobber a URL' '
         svn mkdir -m "mkdir bar" "${svnrepo}2/bar" &&
         git config --unset svn-remote.svn.fetch \
                                 "^bar:refs/remotes/git-svn$" &&
-	! git-svn init "${svnrepo}2/bar"
+	test_must_fail git-svn init "${svnrepo}2/bar"
         '
 
 test_expect_success \
diff --git a/t/t9106-git-svn-commit-diff-clobber.sh b/t/t9106-git-svn-commit-diff-clobber.sh
index 58a3a7b..a57ff68 100755
--- a/t/t9106-git-svn-commit-diff-clobber.sh
+++ b/t/t9106-git-svn-commit-diff-clobber.sh
@@ -27,7 +27,7 @@ test_expect_success 'commit change from svn side' '
 test_expect_success 'commit conflicting change from git' '
 	echo second line from git >> file &&
 	git commit -a -m "second line from git" &&
-	! git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo"
+	test_must_fail git-svn commit-diff -r1 HEAD~1 HEAD "$svnrepo"
 '
 
 test_expect_success 'commit complementing change from git' '
@@ -52,7 +52,7 @@ test_expect_success 'dcommit fails to commit because of conflict' '
 	rm -rf t.svn &&
 	echo "fourth line from git" >> file &&
 	git commit -a -m "fourth line from git" &&
-	! git-svn dcommit
+	test_must_fail git-svn dcommit
 	'
 
 test_expect_success 'dcommit does the svn equivalent of an index merge' "
@@ -83,7 +83,7 @@ test_expect_success 'multiple dcommit from git-svn will not clobber svn' "
 	git commit -a -m 'new file' &&
 	echo clobber > file &&
 	git commit -a -m 'clobber' &&
-	! git svn dcommit
+	test_must_fail git svn dcommit
 	"
 
 
diff --git a/t/t9106-git-svn-dcommit-clobber-series.sh b/t/t9106-git-svn-dcommit-clobber-series.sh
index f8f4718..bc37db9 100755
--- a/t/t9106-git-svn-dcommit-clobber-series.sh
+++ b/t/t9106-git-svn-dcommit-clobber-series.sh
@@ -57,7 +57,7 @@ test_expect_success 'change file but in unrelated area' "
 test_expect_success 'attempt to dcommit with a dirty index' '
 	echo foo >>file &&
 	git add file &&
-	! git svn dcommit
+	test_must_fail git svn dcommit
 '
 
 test_done
diff --git a/t/t9200-git-cvsexportcommit.sh b/t/t9200-git-cvsexportcommit.sh
index b1dc32d..3e32e84 100755
--- a/t/t9200-git-cvsexportcommit.sh
+++ b/t/t9200-git-cvsexportcommit.sh
@@ -100,7 +100,7 @@ test_expect_success \
      git commit -a -m "generation 2" &&
      id=$(git rev-list --max-count=1 HEAD) &&
      (cd "$CVSWORK" &&
-     ! git cvsexportcommit -c $id
+     test_must_fail git cvsexportcommit -c $id
      )'
 
 #test_expect_success \
@@ -112,7 +112,7 @@ test_expect_success \
 #     git commit -a -m "generation 3" &&
 #     id=$(git rev-list --max-count=1 HEAD) &&
 #     (cd "$CVSWORK" &&
-#     ! git cvsexportcommit -c $id
+#     test_must_fail git cvsexportcommit -c $id
 #     )'
 
 # We reuse the state from two tests back here
@@ -222,7 +222,7 @@ test_expect_success \
       git commit -a -m "Update two" &&
       id=$(git rev-list --max-count=1 HEAD) &&
       (cd "$CVSWORK" &&
-      ! git-cvsexportcommit -c $id
+      test_must_fail git-cvsexportcommit -c $id
       )'
 
 case "$(git config --bool core.filemode)" in
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 5edf56f..e17afa8 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -166,7 +166,7 @@ M 755 0000000000000000000000000000000000000001 zero1
 
 INPUT_END
 test_expect_success 'B: fail on invalid blob sha1' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -181,7 +181,7 @@ from refs/heads/master
 
 INPUT_END
 test_expect_success 'B: fail on invalid branch name ".badbranchname"' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -196,7 +196,7 @@ from refs/heads/master
 
 INPUT_END
 test_expect_success 'B: fail on invalid branch name "bad[branch]name"' '
-    ! git-fast-import <input
+    test_must_fail git-fast-import <input
 '
 rm -f .git/objects/pack_* .git/objects/index_*
 
@@ -340,7 +340,7 @@ from refs/heads/branch^0
 
 INPUT_END
 test_expect_success 'E: rfc2822 date, --date-format=raw' '
-    ! git-fast-import --date-format=raw <input
+    test_must_fail git-fast-import --date-format=raw <input
 '
 test_expect_success \
     'E: rfc2822 date, --date-format=rfc2822' \
diff --git a/t/t9301-fast-export.sh b/t/t9301-fast-export.sh
index f1bc5ce..0959f2f 100755
--- a/t/t9301-fast-export.sh
+++ b/t/t9301-fast-export.sh
@@ -59,7 +59,7 @@ test_expect_success 'fast-export master~2..master' '
 		 test $MASTER != $(git rev-parse --verify refs/heads/partial) &&
 		 git diff master..partial &&
 		 git diff master^..partial^ &&
-		 ! git rev-parse partial~2)
+		 test_must_fail git rev-parse partial~2)
 
 '
 
@@ -125,7 +125,7 @@ test_expect_success 'set up faked signed tag' '
 
 test_expect_success 'signed-tags=abort' '
 
-	! git fast-export --signed-tags=abort sign-your-name
+	test_must_fail git fast-export --signed-tags=abort sign-your-name
 
 '
 
-- 
1.5.6.2.303.g79662

^ permalink raw reply related

* [PATCH] Make rebase--interactive use OPTIONS_SPEC
From: Stephan Beyer @ 2008-07-12 15:48 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, Junio C Hamano, Stephan Beyer

Also add some checks that --continue/--abort/--skip
actions are used without --onto, -p, -t, etc.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---

Yes, I've already sent a similar patch, that was dropped because it
depended on the js/rebase-i-sequencer patches that are dropped.

Now I picked this out of my sequencer patchset because it is general
enough.

 git-rebase--interactive.sh |   77 +++++++++++++++++++++++++++++---------------
 1 files changed, 51 insertions(+), 26 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index a64d9d5..3d85486 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -10,10 +10,24 @@
 # The original idea comes from Eric W. Biederman, in
 # http://article.gmane.org/gmane.comp.version-control.git/22407
 
-USAGE='(--continue | --abort | --skip | [--preserve-merges] [--verbose]
-	[--onto <branch>] <upstream> [<branch>])'
+OPTIONS_KEEPDASHDASH=
+OPTIONS_SPEC="\
+git-rebase [-i] [options] [--] <upstream> [<branch>]
+git-rebase [-i] (--continue | --abort | --skip)
+--
+ Available options are
+v,verbose          display a diffstat of what changed upstream
+onto=              rebase onto given branch instead of upstream
+p,preserve-merges  try to recreate merges instead of ignoring them
+s,strategy=        use the given merge strategy
+m,merge            always used (no-op)
+i,interactive      always used (no-op)
+ Actions:
+continue           continue rebasing process
+abort              abort rebasing process and restore original branch
+skip               skip current patch and continue rebasing process
+"
 
-OPTIONS_SPEC=
 . git-sh-setup
 require_work_tree
 
@@ -25,10 +39,8 @@ SQUASH_MSG="$DOTEST"/message-squash
 REWRITTEN="$DOTEST"/rewritten
 PRESERVE_MERGES=
 STRATEGY=
+ONTO=
 VERBOSE=
-test -d "$REWRITTEN" && PRESERVE_MERGES=t
-test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
-test -f "$DOTEST"/verbose && VERBOSE=t
 
 GIT_CHERRY_PICK_HELP="  After resolving the conflicts,
 mark the corrected paths with 'git add <paths>', and
@@ -366,10 +378,27 @@ do_rest () {
 	done
 }
 
+# check if no other options are set
+is_standalone () {
+	test $# -eq 2 -a "$2" = '--' &&
+	test -z "$ONTO" &&
+	test -z "$PRESERVE_MERGES" &&
+	test -z "$STRATEGY" &&
+	test -z "$VERBOSE"
+}
+
+get_saved_options () {
+	test -d "$REWRITTEN" && PRESERVE_MERGES=t
+	test -f "$DOTEST"/strategy && STRATEGY="$(cat "$DOTEST"/strategy)"
+	test -f "$DOTEST"/verbose && VERBOSE=t
+}
+
 while test $# != 0
 do
 	case "$1" in
 	--continue)
+		is_standalone "$@" || usage
+		get_saved_options
 		comment_for_reflog continue
 
 		test -d "$DOTEST" || die "No interactive rebase running"
@@ -402,6 +431,8 @@ do
 		do_rest
 		;;
 	--abort)
+		is_standalone "$@" || usage
+		get_saved_options
 		comment_for_reflog abort
 
 		git rerere clear
@@ -419,6 +450,8 @@ do
 		exit
 		;;
 	--skip)
+		is_standalone "$@" || usage
+		get_saved_options
 		comment_for_reflog skip
 
 		git rerere clear
@@ -426,7 +459,7 @@ do
 
 		output git reset --hard && do_rest
 		;;
-	-s|--strategy)
+	-s)
 		case "$#,$1" in
 		*,*=*)
 			STRATEGY="-s "$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
@@ -437,25 +470,26 @@ do
 			shift ;;
 		esac
 		;;
-	-m|--merge)
+	-m)
 		# we use merge anyway
 		;;
-	-C*)
-		die "Interactive rebase uses merge, so $1 does not make sense"
-		;;
-	-v|--verbose)
+	-v)
 		VERBOSE=t
 		;;
-	-p|--preserve-merges)
+	-p)
 		PRESERVE_MERGES=t
 		;;
-	-i|--interactive)
+	-i)
 		# yeah, we know
 		;;
-	''|-h)
-		usage
+	--onto)
+		shift
+		ONTO=$(git rev-parse --verify "$1") ||
+			die "Does not point to a valid commit: $1"
 		;;
-	*)
+	--)
+		shift
+		test $# -eq 1 -o $# -eq 2 || usage
 		test -d "$DOTEST" &&
 			die "Interactive rebase already started"
 
@@ -464,15 +498,6 @@ do
 
 		comment_for_reflog start
 
-		ONTO=
-		case "$1" in
-		--onto)
-			ONTO=$(git rev-parse --verify "$2") ||
-				die "Does not point to a valid commit: $2"
-			shift; shift
-			;;
-		esac
-
 		require_clean_work_tree
 
 		UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
-- 
1.5.6.2.303.g79662

^ permalink raw reply related

* [PATCH 1/2] t/test-lib.sh: Let test_must_fail fail on signals only
From: Stephan Beyer @ 2008-07-12 15:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Stephan Beyer

The test_must_fail function in test-lib.sh has been designed
to distinguish segmentation faults from controlled errors.
But in the current implementation this only works if a git
command does not return a small negative value, like -1, -2
or -3. But some git commands do.

Because any signal (like SIGSEGV) will result in an exit status
less than 193, this patch just adds a further check for the exit
status.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
 t/test-lib.sh |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index 8e2849b..11c0275 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -379,7 +379,7 @@ test_external_without_stderr () {
 
 test_must_fail () {
 	"$@"
-	test $? -gt 0 -a $? -le 129
+	test $? -gt 0 -a $? -le 129 -o $? -gt 192
 }
 
 # test_cmp is a helper function to compare actual and expected output.
-- 
1.5.6.2.303.g79662

^ permalink raw reply related

* [PATCH] t3404: Let "preserve merges with -p" check two cases
From: Stephan Beyer @ 2008-07-12 15:47 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, Stephan Beyer

There are two cases for preserving merges:
1. The merge base is outside the trunk that is to be rebased.
   Then commits of those other parents must not be picked.
2. The merge base is inside the trunk that is to be rebased.
   Then all the commits related to that merge must be picked
   and the merge must be redone.

The "preserve merges with -p" test case tested for case 1 only.
This patch adds case 2.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
 t/t3404-rebase-interactive.sh |   26 +++++++++++++++++++++-----
 1 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 1c80148..092aa26 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -211,7 +211,7 @@ test_expect_success 'preserve merges with -p' '
 	git add unrelated-file &&
 	test_tick &&
 	git commit -m "unrelated" &&
-	git checkout -b to-be-rebased master &&
+	git checkout -b another-branch master &&
 	echo B > file1 &&
 	test_tick &&
 	git commit -m J file1 &&
@@ -220,12 +220,28 @@ test_expect_success 'preserve merges with -p' '
 	echo C > file1 &&
 	test_tick &&
 	git commit -m K file1 &&
+	echo D > file1 &&
+	test_tick &&
+	git commit -m L1 file1 &&
+	git checkout HEAD^ &&
+	echo 1 > unrelated-file &&
+	test_tick &&
+	git commit -m L2 unrelated-file &&
+	test_tick &&
+	git merge another-branch &&
+	echo E > file1 &&
+	test_tick &&
+	git commit -m M file1 &&
+	git checkout -b to-be-rebased &&
 	test_tick &&
 	git rebase -i -p --onto branch1 master &&
-	test $(git rev-parse HEAD^^2) = $(git rev-parse to-be-preserved) &&
-	test $(git rev-parse HEAD~3) = $(git rev-parse branch1) &&
-	test $(git show HEAD:file1) = C &&
-	test $(git show HEAD~2:file1) = B
+	test $(git rev-parse HEAD~6) = $(git rev-parse branch1) &&
+	test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) &&
+	test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) &&
+	test $(git show HEAD~5:file1) = B &&
+	test $(git show HEAD~3:file1) = C &&
+	test $(git show HEAD:file1) = E &&
+	test $(git show HEAD:unrelated-file) = 1
 '
 
 test_expect_success '--continue tries to commit' '
-- 
1.5.6.2.303.g79662

^ permalink raw reply related

* [PATCH] git-am/git-mailsplit: correct synopsis for reading from stdin
From: Stephan Beyer @ 2008-07-12 15:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Stephan Beyer

Invoking git-am or git-mailsplit without mbox or Maildir results
in reading an mbox from stdin.
This should be mentioned in the synopsis and usage strings.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
 Documentation/git-am.txt |    4 ++--
 builtin-mailsplit.c      |    2 +-
 git-am.sh                |    2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 3863eeb..2842880 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -12,8 +12,8 @@ SYNOPSIS
 'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
          [--3way] [--interactive] [--binary]
          [--whitespace=<option>] [-C<n>] [-p<n>]
-         <mbox>|<Maildir>...
-'git am' [--skip | --resolved]
+         [<mbox> | <Maildir>...]
+'git am' (--skip | --resolved)
 
 DESCRIPTION
 -----------
diff --git a/builtin-mailsplit.c b/builtin-mailsplit.c
index ae2b4cb..e8cbe67 100644
--- a/builtin-mailsplit.c
+++ b/builtin-mailsplit.c
@@ -9,7 +9,7 @@
 #include "path-list.h"
 
 static const char git_mailsplit_usage[] =
-"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> <mbox>|<Maildir>...";
+"git-mailsplit [-d<prec>] [-f<n>] [-b] -o<directory> [<mbox>|<Maildir>...]";
 
 static int is_from_line(const char *line, int len)
 {
diff --git a/git-am.sh b/git-am.sh
index 83b277a..4e73f93 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -5,7 +5,7 @@
 SUBDIRECTORY_OK=Yes
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
-git-am [options] <mbox>|<Maildir>...
+git-am [options] [<mbox>|<Maildir>...]
 git-am [options] --resolved
 git-am [options] --skip
 --
-- 
1.5.6.2.303.g79662

^ permalink raw reply related

* [PATCH] git-am: Do not exit silently if committer is unset
From: Stephan Beyer @ 2008-07-12 15:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Stephan Beyer

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
 git-am.sh |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/git-am.sh b/git-am.sh
index 2c517ed..83b277a 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -30,7 +30,8 @@ set_reflog_action am
 require_work_tree
 cd_to_toplevel
 
-git var GIT_COMMITTER_IDENT >/dev/null || exit
+git var GIT_COMMITTER_IDENT >/dev/null ||
+	die "You need to set your committer info first"
 
 stop_here () {
     echo "$1" >"$dotest/next"
-- 
1.5.6.2.303.g79662

^ permalink raw reply related

* Re: [PATCH 0/3] Git::Repo API and gitweb caching
From: Jakub Narebski @ 2008-07-12 15:08 UTC (permalink / raw)
  To: Abhijit Menon-Sen
  Cc: Lea Wiemann, git, John Hawley, Petr Baudis, Johannes Schindelin
In-Reply-To: <20080711162752.GA5456@toroid.org>

Abhijit Menon-Sen <ams@toroid.org> writes:

> At 2008-07-11 16:07:26 +0200, lewiemann@gmail.com wrote:
> >
> > > 'If-Not-Modified-Since', 'If-Match' (by caches)
> > 
> > Wait, are you sure caches would use those headers (I believe only the
> > latter actually exists BTW), or did you fall prey to a thinko? ;)
> 
> If-Not-Modified-Since should really be If-Unmodified-Since.
> 
> But where's the thinko? To send If-Modified-Since or similar with a
> request, you would need to have a cached copy of the resource and use
> its Last-Modified, for example. Sure, you could do it without one, but
> what would be the point?

Actually the thinko was use of If-Unmodified-Since: and If-Match:.

Both If-Unmodified-Since and If-Match can be used and should be used
when requesting *partial document transfers* (when you need to ensure
that document is unchanged before you fetch next part of it).  
Additionally If-Match can be used for concurrenty control when you
do a two-way communication using GET and PUT, in a PUT request to
ensure that you are modifying correct document.

They are not used, I think, by caches to refresh cached data.
-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* [PATCH 2/2 (for GIT-GUI)] git-gui: MERGE_RR lives in .git/ directly with newer Git versions
From: Johannes Schindelin @ 2008-07-12 14:56 UTC (permalink / raw)
  To: Kalle Olavi Niemitalo; +Cc: git, gitster, spearce
In-Reply-To: <alpine.DEB.1.00.0807121553120.8950@racer>


Now that MERGE_RR was moved out of .git/rr-cache/, we have to delete
it somewhere else.  Just in case somebody wants to use a newer git-gui
with an older Git, the file .git/rr-cache/MERGE_RR is removed, too (if
it exists).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 git-gui/lib/merge.tcl |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/lib/merge.tcl b/lib/merge.tcl
index cc26b07..5c01875 100644
--- a/lib/merge.tcl
+++ b/lib/merge.tcl
@@ -257,6 +257,7 @@ proc _reset_wait {fd} {
 
 		catch {file delete [gitdir MERGE_HEAD]}
 		catch {file delete [gitdir rr-cache MERGE_RR]}
+		catch {file delete [gitdir MERGE_RR]}
 		catch {file delete [gitdir SQUASH_MSG]}
 		catch {file delete [gitdir MERGE_MSG]}
 		catch {file delete [gitdir GITGUI_MSG]}
-- 
1.5.6.2.511.ge432a

^ permalink raw reply related

* [PATCH 1/2] Move MERGE_RR from .git/rr-cache/ into .git/
From: Johannes Schindelin @ 2008-07-12 14:56 UTC (permalink / raw)
  To: Kalle Olavi Niemitalo; +Cc: git, gitster, spearce
In-Reply-To: <87skufmjg4.fsf@Astalo.kon.iki.fi>


If you want to reuse the rerere cache in another repository, and set
a symbolic link to it, you do not want to have the two repositories
interfer with each other by accessing the _same_ MERGE_RR.

For example, if you use contrib/git-new-workdir to set up a second
working directory, and you have a conflict in one working directory,
but commit in the other working directory first, the wrong "resolution"
will be recorded.

The easy solution is to move MERGE_RR out of the rr-cache/ directory,
which also corresponds with the notion that rr-cache/ contains cached
resolutions, not some intermediate temporary states.

Noticed by Kalle Olavi Niemitalo.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	Shawn, I Cc:ed you because of 2/2.

	On Sat, 12 Jul 2008, Kalle Olavi Niemitalo wrote:

	> I don't see any way to modify the symlinks made by 
	> git-new-workdir so that new SHA-1 directories in .git/rr-cache
	> would be shared but .git/rr-cache/MERGE_RR would not.  On IRC, 
	> "gitte" suggested changing Git to use $GIT_DIR/MERGE_RR instead of 
	> $GIT_DIR/rr-cache/MERGE_RR.

	"gitte" actually expected that a patch would not be that hard.

	> I suppose compatibility with people's existing repositories 
	> would require the modified Git to keep reading 
	> $GIT_DIR/rr-cache/MERGE_RR too, so that Git could be painlessly 
	> upgraded during a merge, but it is not obvious to me how lock files 
	> should then work.

	"rerere" is not perfect.  Thus, I suspect that we can just leave 
	an existing MERGE_RR alone, and the user just has to record the 
	resolution another time.  Too bad.

 branch.c          |    2 +-
 builtin-rerere.c  |    2 +-
 t/t4200-rerere.sh |    6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/branch.c b/branch.c
index 56e9492..b1e59f2 100644
--- a/branch.c
+++ b/branch.c
@@ -166,7 +166,7 @@ void create_branch(const char *head,
 void remove_branch_state(void)
 {
 	unlink(git_path("MERGE_HEAD"));
-	unlink(git_path("rr-cache/MERGE_RR"));
+	unlink(git_path("MERGE_RR"));
 	unlink(git_path("MERGE_MSG"));
 	unlink(git_path("SQUASH_MSG"));
 }
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 69c3a52..1db2e0c 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -429,7 +429,7 @@ static int setup_rerere(struct path_list *merge_rr)
 	if (!is_rerere_enabled())
 		return -1;
 
-	merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR"));
+	merge_rr_path = xstrdup(git_path("MERGE_RR"));
 	fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
 	read_rr(merge_rr);
 	return fd;
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index cf10557..b5a4202 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -57,7 +57,7 @@ test_expect_success 'conflicting merge' '
 	! git merge first
 '
 
-sha1=$(sed -e 's/	.*//' .git/rr-cache/MERGE_RR)
+sha1=$(sed -e 's/	.*//' .git/MERGE_RR)
 rr=.git/rr-cache/$sha1
 test_expect_success 'recorded preimage' "grep ^=======$ $rr/preimage"
 
@@ -143,7 +143,7 @@ test_expect_success 'rerere kicked in' "! grep ^=======$ a1"
 test_expect_success 'rerere prefers first change' 'test_cmp a1 expect'
 
 rm $rr/postimage
-echo "$sha1	a1" | perl -pe 'y/\012/\000/' > .git/rr-cache/MERGE_RR
+echo "$sha1	a1" | perl -pe 'y/\012/\000/' > .git/MERGE_RR
 
 test_expect_success 'rerere clear' 'git rerere clear'
 
@@ -190,7 +190,7 @@ test_expect_success 'file2 added differently in two branches' '
 	git add file2 &&
 	git commit -m version2 &&
 	! git merge fourth &&
-	sha1=$(sed -e "s/	.*//" .git/rr-cache/MERGE_RR) &&
+	sha1=$(sed -e "s/	.*//" .git/MERGE_RR) &&
 	rr=.git/rr-cache/$sha1 &&
 	echo Cello > file2 &&
 	git add file2 &&
-- 
1.5.6.2.511.ge432a

^ permalink raw reply related

* Re: tests for git-p4
From: Johannes Schindelin @ 2008-07-12 14:36 UTC (permalink / raw)
  To: Matt McClure; +Cc: git
In-Reply-To: <e48c5e540807120524rabdcfa6vd91c16ef1b0f80a0@mail.gmail.com>

Hi,

On Sat, 12 Jul 2008, Matt McClure wrote:

> Would my tests be of interest to git-p4's authors?  Is there any 
> existing test framework for git-p4 that I missed?

git$ git shortlog -e -s -n -- contrib/fast-import/git-p4* | head -n 5
   102  Simon Hausmann <simon@lst.de>
    50  Simon Hausmann <shausman@trolltech.com>
    31  Han-Wen Nienhuys <hanwen@google.com>
    13  Simon Hausmann <hausmann@kde.org>
     7  Marius Storm-Olsen <marius@trolltech.com>

Hth,
Dscho

^ permalink raw reply

* Re: [RFC/PATCH (WIP)] Git.pm: Add get_config() method and related subroutines
From: Jakub Narebski @ 2008-07-12 14:31 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git, Lea Wiemann
In-Reply-To: <20080712134553.GC10151@machine.or.cz>

On Sat, Jul 12, 2008, Petr Baudis wrote:
> On Sat, Jul 12, 2008 at 02:35:48PM +0200, Jakub Narebski wrote:
>> On Sat, Jul 12, 2008, Petr Baudis wrote:
 
>> On the other hand if one uses (assuming now Git::Config object API)
>> 
>>   $conf = $repo->get_config('section');
>> 
>> one could access configuration variable values _without_ prefixing
>> them with subsection name, i.e.
>> 
>>   $conf->get('variable');
>> 
>> and not
>> 
>>   $conf->get('section.variable');
>> 
>> 
>> I'm not sure if it is much of an improvement.
> 
> I would propose not to go with this feature yet and add it only when
> justified by accompanied cleanups of real code using this.

O.K.
 
>> The former plays better with
>> 
>>   $r->get_config()->bool('gitweb.blame');
>> 
>> but this is nevertheless not recommended workflow; you can use
>> 
>>   $r->config_bool('gitweb.blame');
>> 
>> and it would be faster (unless some Perl/OO trickery with singletons
>> and the like).
>> 
>>  Recommended workflow (code) is
>> 
>>   $c = $r->get_config();
>>   ...
>>   $c->get_bool('gitweb.blame');
>> 
>> or something like that.
> 
> I thought that the get_config() method would be reusing existing
> Git::Config instances no-matter-what? (Otherwise, you can get into
> rather tricky issues like one part of the code modifying the config and
> the other not noticing the change, etc. And I can se no benefit. If you
> want to reload the config, we might have method like reload(), but I
> don't think that would be very useful except perhaps in some kind of
> mod_perl'd gitweb scenario.)

Somehow I forgot that $repo can remember existing Git::Config, generate
it only once (and remember it) on demand but fully, and then serve it.
It probably is some OO "pattern" like SingletonFactory or sth...

It would probably play better with Git::Repo object interface, but can
I think work as well with Git->repository(...) instance.


As to changing config: I wasn't even thinking about that... and I don't
think that any command written in Perl which uses or can use either
Git or Git::Repo API needs writing config files.


> But we're arguing about nothing, really, except the exact amount of
> coolness of the Git::Config approach. :-)

True.  For me the fact that one can write $c->value('diff.renameLimit')
or $c->value('diff.renamelimit'); is teh winner ;-)

-- 
Jakub Narebski
Poland

^ permalink raw reply

* Re: [RFC/PATCH (WIP)] Git.pm: Add get_config() method and related subroutines
From: Petr Baudis @ 2008-07-12 13:45 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git, Lea Wiemann
In-Reply-To: <200807121435.49151.jnareb@gmail.com>

On Sat, Jul 12, 2008 at 02:35:48PM +0200, Jakub Narebski wrote:
> On Sat, Jul 12, 2008, Petr Baudis wrote:
> > Or if you mean foreach use, it's trivial to
> > 
> > 	foreach (grep { /^gitweb\./ } keys %$config)
> > 
> > or provide a method of Git::Config that will return this list, but it
> > does not seem appropriate to have specific Git::Config instances for
> > this. (Besides, if the script also needs to access a single variable
> > from a different section, it will need to re-parse the config again.)
> > 
> > So I think your approach would be good only if there are multiple
> > methods of Git::Config that would operate on the whole config and needed
> > a way to be restricted; is that the case?
> 
> On the other hand if one uses (assuming now Git::Config object API)
> 
>   $conf = $repo->get_config('section');
> 
> one could access configuration variable values _without_ prefixing
> them with subsection name, i.e.
> 
>   $conf->get('variable');
> 
> and not
> 
>   $conf->get('section.variable');
> 
> 
> I'm not sure if it is much of an improvement.

I would propose not to go with this feature yet and add it only when
justified by accompanied cleanups of real code using this.

> We can have $c->value(<VAR>), $c->bool(<VAR>), $c->int(<VAR>) and
> (in the future) $c->color(<VAR>) and $c->colorbool(<VAR>)... or we can
> have $c->get(<VAR>), $c->get_bool(<VAR>) etc.

I think I prefer the terser approach of value/bool/int now since it is
shorter and seems to stay pretty unambiguous. Besides, this way we can
easily make mutators by just adding second optional argument to these
methods.

> The former plays better with
> 
>   $r->get_config()->bool('gitweb.blame');
> 
> but this is nevertheless not recommended workflow; you can use
> 
>   $r->config_bool('gitweb.blame');
> 
> and it would be faster (unless some Perl/OO trickery with singletons
> and the like).
> 
>  Recommended workflow (code) is
> 
>   $c = $r->get_config();
>   ...
>   $c->get_bool('gitweb.blame');
> 
> or something like that.

I thought that the get_config() method would be reusing existing
Git::Config instances no-matter-what? (Otherwise, you can get into
rather tricky issues like one part of the code modifying the config and
the other not noticing the change, etc. And I can se no benefit. If you
want to reload the config, we might have method like reload(), but I
don't think that would be very useful except perhaps in some kind of
mod_perl'd gitweb scenario.)

> >>> Also, having accessors for special types lets you return undef when
> >>> the type really isn't defined, instead of e.g. true with current
> >>> config_val_bool, which is clearly bogus and requires complicated code
> >>> on the user side. 
> >>  
> >> I don't follow you.  Didn't we agree on casting an error when variable
> >> is not of given type?
> > 
> > Sorry, s/type really/variable really/. According to your original code,
> > 
> > 	config_val_bool(undef)
> > 
> > would return true, while the undef could be from both non-existent and
> > unassigned variable. (This 'unassigned variables' case is really
> > annoying to handle.)
> 
> That is why you should check exists($config{<VAR>}) first.

And that was my point when I talked about complicated code on the user
side.

But we're arguing about nothing, really, except the exact amount of
coolness of the Git::Config approach. :-)

-- 
				Petr "Pasky" Baudis
GNU, n. An animal of South Africa, which in its domesticated state
resembles a horse, a buffalo and a stag. In its wild condition it is
something like a thunderbolt, an earthquake and a cyclone. -- A. Pierce

^ permalink raw reply

* Re: [PATCH 3/3] imap-send.c: Clean up coding style to better match the rest of the git codebase.
From: Jakub Narebski @ 2008-07-12 12:38 UTC (permalink / raw)
  To: Rob Shearman; +Cc: Junio C Hamano, git
In-Reply-To: <1096648c0807081621x669a9bc4ie484fd004674918d@mail.gmail.com>

On Wed, 9 July 2008, Rob Shearman wrote:
> 2008/7/7 Jakub Narebski <jnareb@gmail.com>:

> > or use either git-send-email
> > (I think you can send patches also via Gmail) or git-imap-send,
> 
> Ok, but git-imap-send only puts the emails into your Drafts folder so
> that you can send them with your normal email client (which is what
> does the linewrapping).

Errr... if you are using normal email client, then it should be
possible to turn off line wrapping in the client, isn't it?
 
[...]
> > then preferred solution is to have patch inline.
> >
> > If it is not possible, then attach the patch, but preferrably
> >  1) with text/plain mimetype (.txt extension instead of .patch or
> >    .diff could be required for that)
> >
> >  2) 8bit (preferred) or quoted-printable (if 8bit is not possible)
> >    transfer encoding (base64 is terrible waste of space); text/plain
> >    should chose quoted-printable at worst
> >
> >  3) use "inline" attachement (select 'suggest to display attachement'
> >    or something like that), so it is possible to select attachement
> >    and hit reply.
> 
> I think this was the case with the patches originally sent, but I used
> "git format-patch --attach --stdout ... | git imap-send" so if the
> mails didn't meet one of those points then it should be fixed in
> git-format-patch.

"git format-patch --inline --stdout", perhaps?

-- 
Jakub Narebski
Poland

^ permalink raw reply

* Re: [RFC/PATCH (WIP)] Git.pm: Add get_config() method and related subroutines
From: Jakub Narebski @ 2008-07-12 12:35 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git, Lea Wiemann
In-Reply-To: <20080712014708.GB10151@machine.or.cz>

On Sat, Jul 12, 2008, Petr Baudis wrote:
> On Thu, Jul 10, 2008 at 01:33:36AM +0200, Jakub Narebski wrote:
>> On Wed, Jul 09, 2008, Petr "Pasky" Baudis wrote:
>>> On Thu, Jul 03, 2008 at 06:24:53PM +0200, Jakub Narebski wrote:

>>>>  * What should ->get_config() have as an optional parameter:
>>>>    PREFIX (/^$prefix/o), or simply SECTION (/^(?:$section)\./o)?
>>> 
>>> Do we even _need_ a parameter like that? I don't understand what is
>>> this interface trying to address.
>> 
>> For example if one wants to access _all_ variables in gitweb.* section
>> (or in gitcvs.* section), and _only_ config variables in given section.
> 
> But what is the practical benefit? Does anyone use a config file long
> enough that this makes any difference?

Probably not.

> Or if you mean foreach use, it's trivial to
> 
> 	foreach (grep { /^gitweb\./ } keys %$config)
> 
> or provide a method of Git::Config that will return this list, but it
> does not seem appropriate to have specific Git::Config instances for
> this. (Besides, if the script also needs to access a single variable
> from a different section, it will need to re-parse the config again.)
> 
> So I think your approach would be good only if there are multiple
> methods of Git::Config that would operate on the whole config and needed
> a way to be restricted; is that the case?

On the other hand if one uses (assuming now Git::Config object API)

  $conf = $repo->get_config('section');

one could access configuration variable values _without_ prefixing
them with subsection name, i.e.

  $conf->get('variable');

and not

  $conf->get('section.variable');


I'm not sure if it is much of an improvement.

>> BTW. what should non-typecasting should be named? $c->get(<VAR>), 
>> $c->value(<VAR>), $c->param(<VAR>), or something yet different?
> 
> I would prefer 'get' since it's the shortest and most clear, but 'value'
> would be fine too, I suppose (and more in line with bool etc.).

Well, that would have to be decided before other programs could use
this API.
 
We can have $c->value(<VAR>), $c->bool(<VAR>), $c->int(<VAR>) and
(in the future) $c->color(<VAR>) and $c->colorbool(<VAR>)... or we can
have $c->get(<VAR>), $c->get_bool(<VAR>) etc.

The former plays better with

  $r->get_config()->bool('gitweb.blame');

but this is nevertheless not recommended workflow; you can use

  $r->config_bool('gitweb.blame');

and it would be faster (unless some Perl/OO trickery with singletons
and the like).  Recommended workflow (code) is

  $c = $r->get_config();
  ...
  $c->get_bool('gitweb.blame');

or something like that.

>>> Also, having accessors for special types lets you return undef when
>>> the type really isn't defined, instead of e.g. true with current
>>> config_val_bool, which is clearly bogus and requires complicated code
>>> on the user side. 
>>  
>> I don't follow you.  Didn't we agree on casting an error when variable
>> is not of given type?
> 
> Sorry, s/type really/variable really/. According to your original code,
> 
> 	config_val_bool(undef)
> 
> would return true, while the undef could be from both non-existent and
> unassigned variable. (This 'unassigned variables' case is really
> annoying to handle.)

That is why you should check exists($config{<VAR>}) first.

-- 
Jakub Narebski
Poland

^ permalink raw reply

* Re: git pull is slow
From: Stephan Hennig @ 2008-07-12 12:32 UTC (permalink / raw)
  To: git; +Cc: Johannes Schindelin, Andreas Ericsson
In-Reply-To: <alpine.DEB.1.00.0807111443280.8950@racer>

Hi,

Johannes Schindelin schrieb:
> On Fri, 11 Jul 2008, Andreas Ericsson wrote:
> 
>> Seems like you're being bitten by a bug we had some months back,
>> where the client requested full history for new tag objects.
> 
> I do not think so.  I think it is a problem with the pack.  The slowness 
> is already there in the clone, in the resolving phase.

Thanks for having a look at this!  What does "problem with the pack"
mean?  Do you think it is a Git problem (client or server side?) or just
a misconfiguration?

Best regards,
Stephan Hennig

^ permalink raw reply

* tests for git-p4
From: Matt McClure @ 2008-07-12 12:24 UTC (permalink / raw)
  To: git

I'm planning to write a "p4-fast-export" that will facilitate using
Bazaar on projects maintained in Perforce.  I'd like to reuse code
from git-p4 since it appears to have much of the functionality I want.
 In fact, the main reason I can't just use git-p4 today is that it
does too much: it pushes the Perforce fast-export representation
directly into Git.  I'm going to work on covering the existing
functionality in tests before I start modifying the code, and I could
try to write those tests such that they'll be useful to the Git
project as well.

Would my tests be of interest to git-p4's authors?  Is there any
existing test framework for git-p4 that I missed?

Matt

^ permalink raw reply

* git-new-workdir should not share .git/rr-cache/MERGE_RR
From: Kalle Olavi Niemitalo @ 2008-07-12 11:27 UTC (permalink / raw)
  To: git

The contrib/workdir/git-new-workdir script makes .git/rr-cache in
each workdir a symlink to the shared .git/rr-cache directory.
This lets git-rerere share conflict resolutions between workdirs.
However, that directory also contains .git/rr-cache/MERGE_RR,
which lists the files for which conflict resolutions should be
saved in the next commit.  It is thus possible that git-merge in
one workdir records conflicts to the shared MERGE_RR file, and
git-commit in another workdir saves the staged files to rr-cache
as conflict resolutions, even though those files are from a
different branch and never saw the merge.  Such invalid conflict
resolutions need then be separately deleted.  This happened to
me, with git version 1.5.6.

I don't see any way to modify the symlinks made by
git-new-workdir so that new SHA-1 directories in .git/rr-cache
would be shared but .git/rr-cache/MERGE_RR would not.  On IRC,
"gitte" suggested changing Git to use $GIT_DIR/MERGE_RR instead
of $GIT_DIR/rr-cache/MERGE_RR.  I suppose compatibility with
people's existing repositories would require the modified Git to
keep reading $GIT_DIR/rr-cache/MERGE_RR too, so that Git could be
painlessly upgraded during a merge, but it is not obvious to me
how lock files should then work.

Alternatively, the SHA-1 directories in .git/rr-cache could be
moved to a subdirectory; then git-new-workdir could be changed to
symlink only that subdirectory.

^ permalink raw reply

* Automatic cherry-pick failure
From: Jelle Geerts @ 2008-07-12 11:55 UTC (permalink / raw)
  To: git

Hello,

When I tried to `git rebase -i', I changed the first line in the editor from
'pick' to 'edit'. After the editor exited, git complained:
  error: Untracked working tree file 'DESIGN.TXT' would be overwritten by merge.
But this file is tracked, so first I did `git rebase --abort'.
I had to use `git config --bool core.ignorecase true' to get around the error.
It's because I use Git with Cygwin on an NTFS partition. Only thing I is that
'core.ignorecase' is undocumented.

After getting around the Cygwin specific workaround, I reran rebase. Again, I
edited the first line from 'pick' to 'edit'. All went well. Then I made the
amendment to the commit with `git commit --amend --author="me <me@somewhere>"'.
Now, when I typed `git rebase --continue' I got this:
  error: Entry 'code/src/sys_main.cc' not uptodate. Cannot merge.
  fatal: merging of trees e3249e935c9ccd790c372aac82b8e097044b1ffe and
ac79e613ed0fe912e0da2c5ccf52f6a540533cb8 failed
  Automatic cherry-pick failed.  After resolving the conflicts,
  mark the corrected paths with 'git add <paths>', and
  run 'git rebase --continue'
  Could not apply 5c03af9... commit test

I'm not sure what I have to do now, can someone help me with this?

-- Jelle

^ permalink raw reply

* [PATCH] t0004: fix timing bug
From: Junio C Hamano @ 2008-07-12 11:14 UTC (permalink / raw)
  To: git

The test created an initial commit, made .git/objects unwritable and then
exercised various codepaths to create loose commit, tree and blob objects
to make sure the commands notice failures from these attempts.

However, the initial commit was not preceded with test_tick, which made
its object name depend on the timestamp.  The names of all the later tree
and blob objects the test tried to create were static.  If the initial
commit's object name happened to begin with the same two hexdigits as the
tree or blob objects the test later attempted to create, the fan-out
directory in which these tree or blob would be created is already created
when the initial commit was made, and the object creation succeeds, and
commands being tested should not notice any failure --- in short, the test
was bogus.

This makes the fan-out directories also unwritable, and adds test_tick
before the commit object creation to make the test repeatable.

The contents of the file to create a blob from "a" to "60" is to force the
name of the blob object to begin with "1b", which shares the fan-out
directory with the initial commit that is created with the test.  This was
useful when diagnosing the breakage of this test.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * I initially hoped that I spotted a bug in the Linux filesystem code
   that lets a quick operation sneak past chmod that is done immediately
   after it or something racy so that I can tease Linus with it, but no
   such luck ;-)  Doubly embarrasing is that the test-bug is mine. 

 t/t0004-unwritable.sh |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/t/t0004-unwritable.sh b/t/t0004-unwritable.sh
index 9255c63..63e1217 100755
--- a/t/t0004-unwritable.sh
+++ b/t/t0004-unwritable.sh
@@ -8,6 +8,7 @@ test_expect_success setup '
 
 	>file &&
 	git add file &&
+	test_tick &&
 	git commit -m initial &&
 	echo >file &&
 	git add file
@@ -17,11 +18,11 @@ test_expect_success setup '
 test_expect_success 'write-tree should notice unwritable repository' '
 
 	(
-		chmod a-w .git/objects
+		chmod a-w .git/objects .git/objects/?? &&
 		test_must_fail git write-tree
 	)
 	status=$?
-	chmod 775 .git/objects
+	chmod 775 .git/objects .git/objects/??
 	(exit $status)
 
 '
@@ -29,11 +30,11 @@ test_expect_success 'write-tree should notice unwritable repository' '
 test_expect_success 'commit should notice unwritable repository' '
 
 	(
-		chmod a-w .git/objects
+		chmod a-w .git/objects .git/objects/?? &&
 		test_must_fail git commit -m second
 	)
 	status=$?
-	chmod 775 .git/objects
+	chmod 775 .git/objects .git/objects/??
 	(exit $status)
 
 '
@@ -41,12 +42,12 @@ test_expect_success 'commit should notice unwritable repository' '
 test_expect_success 'update-index should notice unwritable repository' '
 
 	(
-		echo a >file &&
-		chmod a-w .git/objects
+		echo 6O >file &&
+		chmod a-w .git/objects .git/objects/?? &&
 		test_must_fail git update-index file
 	)
 	status=$?
-	chmod 775 .git/objects
+	chmod 775 .git/objects .git/objects/??
 	(exit $status)
 
 '
@@ -55,11 +56,11 @@ test_expect_success 'add should notice unwritable repository' '
 
 	(
 		echo b >file &&
-		chmod a-w .git/objects
+		chmod a-w .git/objects .git/objects/?? &&
 		test_must_fail git add file
 	)
 	status=$?
-	chmod 775 .git/objects
+	chmod 775 .git/objects .git/objects/??
 	(exit $status)
 
 '

^ permalink raw reply related

* Re: [StGit PATCH 2/2] Reuse the same temp index in a transaction
From: Catalin Marinas @ 2008-07-12 10:24 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git
In-Reply-To: <20080702061314.11361.28297.stgit@yoghurt>

2008/7/2 Karl Hasselström <kha@treskal.com>:
> Instead of making a new temp index every time we need one, just keep
> reusing the same one. And keep track of which tree is currently stored
> in it -- if we do several consecutive successful pushes, it's always
> going to be the "right" tree so that we don't have to call read-tree
> before each patch application.
>
> The motivation behind this change is of course that it makes things
> faster.
>
> (The same simple test as in the previous patch -- pushing 250 patches
> in a 32k-file repository, with one file-level merge necessary per push
> -- went from 0.36 to 0.19 seconds per patch with this patch applied.)

That's an impressive improvement (together with the previous patch).
Is this with the new patch log infrastructure?

Thanks.

-- 
Catalin

^ permalink raw reply

* Re: [StGit PATCH 1/2] Do simple in-index merge with diff+apply instead of read-tree
From: Catalin Marinas @ 2008-07-12 10:22 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git
In-Reply-To: <20080702061243.11361.75544.stgit@yoghurt>

2008/7/2 Karl Hasselström <kha@treskal.com>:
> The advantage is that patch application will resolve some file content
> conflicts for us, so that we'll fall back to merge-recursive less
> often. This is a significant speedup, especially since merge-recursive
> needs to touch the worktree, which means we have to check out the
> index first.

Thanks.

-- 
Catalin

^ permalink raw reply

* Re: [StGit PATCH 03/14] Write to a stack log when stack is modified
From: Catalin Marinas @ 2008-07-12 10:09 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git
In-Reply-To: <20080623123631.GA18347@diana.vm.bytemark.co.uk>

2008/6/23 Karl Hasselström <kha@treskal.com>:
> On 2008-06-20 10:14:29 +0100, Catalin Marinas wrote:
>
>> 2008/6/19 Karl Hasselström <kha@treskal.com>:
>> > I'd actually say the opposite: until we have a good visualizer
>> > that doesn't need the simplified log, we need to have the
>> > simplified log. If I actually have to look at the diffs in the
>> > log, I find gitk indispensible.
>>
>> And what would the simplified log contain if we decide to go with a
>> new scheme? In your proposal, it points to the tree of main log and
>> you get the diff of diffs (which also means that the diffs must be
>> generated for every modification of a patch). Would this be the
>> same? Again, I worry a bit about the overhead to generate the patch
>> diff for every push (with refresh I'm OK). It can be optimised as in
>> the stable branch where we try git-apply followed by a three-way
>> merge (which, BTW, I'd like added before 0.15). If git-apply
>> succeeds, there is no need to re-generate the diff.
>
> Yes, I was imagining a simplified log precisely like the one I've
> currently implemented (a tree with one blob per patch, which contains
> the message, the diff, and some other odds and ends such as the
> author).

At a first look, I'm OK with a simplified log.

> Two optimizations would hopefully make it fast:
>
>  1. If the patch's sha1 hasn't changed, we don't have to regenerate
>     the diff.
>
>  2. If the patch's sha1 has changed, but git apply was sufficient
>     during the merge stage, we can just reuse that patch. We do have
>     to write it to a blob, but we have already generated the diff and
>     don't need to do so again. (I've shamelessly stolen your idea
>     here.)

It can be optimised a bit more to actually apply the diff in the blob
directly rather than the current way of generating the diff (since we
don't store the diff).

> In most cases, (1) would make sure that only a small handful of
> patches would need to be considered. In the cases where a lot of
> patches are touched, such as rebase, (2) would provide a good speedup
> (except for the cases where we had to call merge-recursive, and those
> are slow anyway).

I think it should work. Rebase is indeed my worry but it might be even
faster for most of the patches to apply the blob than computing the
diff. In my experience with the Linux kernel, full merge is rarely
needed.

-- 
Catalin

^ permalink raw reply

* Re: [StGit PATCH] Remove --undo flags from stg commands and docs
From: Catalin Marinas @ 2008-07-12  9:58 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: git
In-Reply-To: <20080708042131.GB2247@diana.vm.bytemark.co.uk>

2008/7/8 Karl Hasselström <kha@treskal.com>:
> On 2008-07-07 21:54:01 +0100, Catalin Marinas wrote:
>
>> 2008/7/4 Karl Hasselström <kha@treskal.com>:
>>
>> > In this one, I've just removed the --undo flag from sync without
>> > adding anything back. Still undetermined if that's OK.
>>
>> I think it should be ok (see the other thread). Anyway, have you
>> heard of anyone else using sync apart from me?
>
> No, I haven't.
>
> I've tried to understand what it does, and as far as I can tell it
> doesn't do quite what I want. (What I want is the ability to 3-way
> merge StGit patch stacks, so that I can modify the same patch stack in
> several places and merge back and forth. From what I recall, the sync
> command is more like a 2-way merge -- that is, it doesn't take the
> last common ancestor into account. But it's been a while since I
> studied it.)

No, the sync command is a 3-way merge between the top of a remote
patch, the top of the current patch (current HEAD actually) and the
bottom of the remote patch as ancestor. It also has a mode to
synchronise with a patch file and it applies the patch onto the bottom
of the current patch and does the merging between patch tops
afterwards.

This is not ideal as I have to deal with safe conflicts several time
(maybe adding git-rerere support would help). If you have better ideas
for keeping two stacks in sync, I'm happy to accept them (or maybe
just a different workflow).

-- 
Catalin

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox