* [PATCH 3/3] Add git-sequencer test suite (t3350)
From: Stephan Beyer @ 2008-07-16 20:45 UTC (permalink / raw)
To: git; +Cc: Stephan Beyer, Daniel Barkalow, Christian Couder, Junio C Hamano
In-Reply-To: <14224c96008f30754acb021bc0af6b6641897a1e.1216233915.git.s-beyer@gmx.net>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
t/t3350-sequencer.sh | 838 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 838 insertions(+), 0 deletions(-)
create mode 100755 t/t3350-sequencer.sh
diff --git a/t/t3350-sequencer.sh b/t/t3350-sequencer.sh
new file mode 100755
index 0000000..3cc7da8
--- /dev/null
+++ b/t/t3350-sequencer.sh
@@ -0,0 +1,838 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Stephan Beyer
+#
+# `setup' is based on t3404* by Johannes Schindelin.
+
+test_description='git sequencer
+
+These are basic usage tests for git sequencer.
+'
+. ./test-lib.sh
+
+# set up two branches like this:
+#
+# A - B - C - D - E
+# \
+# F - G - H
+# \
+# I
+#
+# where B, D and G touch increment value in file1.
+# The others generate empty file[23456].
+
+SEQDIR=".git/sequencer"
+SEQMARK="refs/sequencer-marks"
+MARKDIR=".git/$SEQMARK"
+
+test_expect_success 'setup' '
+ : >file1 &&
+ git add file1 &&
+ test_tick &&
+ git commit -m "generate empty file1" &&
+ git tag A &&
+ echo 1 >file1 &&
+ test_tick &&
+ git commit -m "write 1 into file1" file1 &&
+ git tag B &&
+ : >file2 &&
+ git add file2 &&
+ test_tick &&
+ git commit -m "generate empty file2" &&
+ git tag C &&
+ echo 2 >file1 &&
+ test_tick &&
+ git commit -m "write 2 into file1" file1 &&
+ git tag D &&
+ : >file3 &&
+ git add file3 &&
+ test_tick &&
+ git commit -m "generate empty file3" &&
+ git tag E &&
+ git checkout -b branch1 A &&
+ : >file4 &&
+ git add file4 &&
+ test_tick &&
+ git commit -m "generate empty file4" &&
+ git tag F &&
+ echo 3 >file1 &&
+ test_tick &&
+ git commit -m "write 3 into file1" file1 &&
+ git tag G &&
+ : >file5 &&
+ git add file5 &&
+ test_tick &&
+ git commit -m "generate empty file5" &&
+ git tag H &&
+ git checkout -b branch2 F &&
+ : >file6 &&
+ git add file6 &&
+ test_tick &&
+ git commit -m "generate empty file6" &&
+ git tag I &&
+ git diff -p --raw C..D >patchD.raw &&
+ git diff -p --raw A..F >patchF.raw &&
+ git format-patch --stdout A..B >patchB &&
+ git format-patch --stdout B..C >patchC &&
+ git format-patch --stdout C..D >patchD &&
+ git format-patch --stdout A..F >patchF &&
+ git format-patch --stdout F..G >patchG
+'
+
+orig_author="$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>"
+
+# Functions to verify exit status of sequencer.
+# Do not just use "test_must_fail git sequencer ..."!
+expect_fail () {
+ "$@"
+ test $? -eq 1
+}
+expect_continue () {
+ "$@"
+ test $? -eq 2
+}
+expect_conflict () {
+ "$@"
+ test $? -eq 3
+}
+
+
+# Other test helpers:
+
+# Test if commit $1 has author $2
+expect_author () {
+ test "$2" = "$(git cat-file commit "$1" |
+ sed -n -e "s/^author \(.*\)> .*$/\1>/p")"
+}
+
+# Test if commit $1 has commit message in file $2
+# Side effect: overwrites actual
+expect_msg () {
+ git cat-file commit "$1" | sed -e "1,/^$/d" >actual &&
+ test_cmp "$2" actual
+}
+
+# Test that no marks are set.
+no_marks_set () {
+ if test -e "$MARKDIR"
+ then
+ rmdir "$MARKDIR"
+ fi
+}
+
+test_expect_success 'fail on empty TODO from stdin' '
+ expect_fail git sequencer <file6 &&
+ ! test -d "$SEQDIR"
+'
+
+# Generate fake editor
+#
+# Simple and practical concept:
+# We use only a small string identifier for "editor sessions".
+# Each sessions knows what to do and perhaps defines
+# which session to choose next.
+echo "#!$SHELL_PATH" >fake-editor.sh
+cat >>fake-editor.sh <<\EOF
+test -f fake-editor-session || exit 1
+#test -t 1 || exit 1
+# This test could be useful, but as the test-lib is not always
+# verbose, this will fail.
+next=ok
+read this <fake-editor-session
+case "$this" in
+commitmsg)
+ echo 'echo 2 >file1'
+ ;;
+squashCE)
+ echo 'generate file2 and file3'
+ ;;
+squashCI)
+ echo 'generate file2 and file6'
+ next=squashDCE
+ ;;
+squashDCE)
+ echo 'generate file2 and file3 and write 2 into file1'
+ next=merge1
+ ;;
+merge1)
+ echo 'A typed merge message.'
+ ;;
+merge2)
+ test "$(sed -n -e 1p "$1")" = 'test merge' &&
+ echo 'cleanup merge' ||
+ echo error
+ sed -e 1d "$1"
+ ;;
+editXXXXXXXXX)
+ printf 'last edited'
+ ;;
+edit*)
+ printf 'edited: '
+ cat "$1"
+ next="${this}X"
+ ;;
+nochange)
+ cat "$1"
+ ;;
+ok|fail)
+ echo '-- THIS IS UNEXPECTED --'
+ next=fail
+ ;;
+*)
+ echo 'I do not know.'
+ ;;
+esac >"$1".tmp
+mv "$1".tmp "$1"
+echo $next >fake-editor-session
+exit 0
+EOF
+chmod a+x fake-editor.sh
+test_set_editor "$(pwd)/fake-editor.sh"
+
+next_session () {
+ echo "$1" >fake-editor-session
+}
+
+# check if fake-editor-session is ok.
+# If "$1" is set to anything, it will set the
+# next session to "ok", which is nice for
+# test_expect_failure.
+session_ok () {
+ test "ok" = $(cat fake-editor-session)
+ ret=$?
+ test -n "$1" && next_session ok
+ return $ret
+}
+
+
+cat >todotest1 <<EOF
+pick C
+squash E
+ref refs/tags/CE
+EOF
+
+test_expect_success '"pick", "squash", "ref" from stdin' '
+ next_session squashCE &&
+ git sequencer <todotest1 &&
+ ! test -d "$SEQDIR" &&
+ session_ok &&
+ test -f file2 &&
+ test -f file3 &&
+ test $(git rev-parse CE) = $(git rev-parse HEAD) &&
+ test $(git rev-parse I) = $(git rev-parse HEAD^)
+'
+
+cat >todotest2 <<EOF
+# This is a test
+
+reset I # go back to I
+
+EOF
+
+test_expect_success '"reset" from file with comments and blank lines' '
+ git sequencer todotest2 &&
+ session_ok &&
+ test $(git rev-parse I) = $(git rev-parse HEAD)
+'
+
+cat >todotest1 <<EOF
+pick C
+EOF
+
+test_expect_success '--onto <branch> keeps branch' '
+ git checkout -b test-branch A &&
+ git checkout master &&
+ git sequencer --onto test-branch <todotest1 &&
+ session_ok &&
+ test "$(git symbolic-ref -q HEAD)" = "refs/heads/test-branch" &&
+ test "$(git rev-parse test-branch^)" = "$(git rev-parse A)"
+'
+
+test_expect_success '--onto commit (detached HEAD) works' '
+ git sequencer --onto A <todotest1 &&
+ session_ok &&
+ test_must_fail git symbolic-ref -q HEAD &&
+ test "$(git rev-parse HEAD)" = "$(git rev-parse test-branch)"
+'
+
+echo 'pick -R C' >>todotest1
+
+test_expect_success 'pick -R works' '
+ git checkout A &&
+ git sequencer todotest1 &&
+ session_ok &&
+ ! test -f file2
+'
+
+mkdir testdir
+cat >testdir/script <<EOF
+#!/bin/sh
+test -s ../file1
+EOF
+chmod 755 testdir/script
+cat >todotest1 <<EOF
+run -- test -s file1 # this will fail
+pick B
+run --dir testdir -- test -s ../file1
+pick D
+run --dir=testdir ./script
+EOF
+
+test_expect_success '"run" insn works' '
+ git checkout A &&
+ expect_conflict git sequencer todotest1 &&
+ : >newfile &&
+ git add newfile &&
+ next_session nochange &&
+ git sequencer --continue &&
+ session_ok &&
+ test -f newfile
+'
+
+echo thisdoesnotexist >>todotest1
+
+test_expect_success 'junk is conflict' '
+ git checkout A &&
+ expect_conflict git sequencer todotest1 &&
+ test -d "$SEQDIR" &&
+ git sequencer --abort &&
+ ! test -d "$SEQDIR" &&
+ session_ok &&
+ test $(git rev-parse A) = $(git rev-parse HEAD)
+'
+
+GIT_AUTHOR_NAME="Another 'ant' Thor"
+GIT_AUTHOR_EMAIL="a.thor@example.com"
+GIT_COMMITTER_NAME="Co M Miter"
+GIT_COMMITTER_EMAIL="c.miter@example.com"
+export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL
+yet_another="Max Min <mm@example.com>"
+
+cat >todotest1 <<EOF
+patch patchB # write 1 into file1
+patch -k patchC # generate file2
+patch patchD.raw # write 2 into file1
+EOF
+
+echo 'write 1 into file1' >expected1
+echo '[PATCH] generate empty file2' >expected2
+echo 'echo 2 >file1' >expected3
+
+test_expect_success '"patch" insn works' '
+ git checkout A &&
+ next_session commitmsg &&
+ git sequencer todotest1 &&
+ ! test -d "$SEQDIR" &&
+ session_ok &&
+ test "$(git rev-parse HEAD~3)" = "$(git rev-parse A)" &&
+ test "$(git show HEAD~2:file1)" = "1" &&
+ test -z "$(git show HEAD^:file2)" &&
+ test "$(git show HEAD:file1)" = "2" &&
+ expect_author HEAD~2 "$orig_author" &&
+ expect_author HEAD~1 "$orig_author" &&
+ expect_author HEAD~0 "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
+ expect_msg HEAD~2 expected1 &&
+ expect_msg HEAD~1 expected2 &&
+ expect_msg HEAD~0 expected3
+'
+
+cat >todotest1 <<EOF
+pick B # write 1 into file1
+pause
+pick C # generate file2
+EOF
+
+echo 'generate empty file2' >expected1
+echo 'write 1 into file1' >expected2
+
+test_expect_success "pick ; pause insns and --continue works" '
+ git checkout A &&
+ expect_continue git sequencer todotest1 &&
+ session_ok &&
+ echo 5 >file1 &&
+ git add file1 &&
+ next_session nochange &&
+ git sequencer --continue &&
+ test "$(git show HEAD:file1)" = 5 &&
+ test -z "$(git show HEAD:file2)" &&
+ expect_msg HEAD expected1 &&
+ expect_msg HEAD^ expected2 &&
+ session_ok
+'
+
+cat >todotest1 <<EOF
+edit B # write 1 into file1
+pick C # generate file2
+EOF
+
+test_expect_success "edit insn and --continue works" '
+ git checkout A &&
+ expect_continue git sequencer todotest1 &&
+ session_ok &&
+ echo 5 >file1 &&
+ git add file1 &&
+ next_session nochange &&
+ git sequencer --continue &&
+ test "$(git show HEAD:file1)" = 5 &&
+ test -z "$(git show HEAD:file2)" &&
+ expect_msg HEAD expected1 &&
+ expect_msg HEAD^ expected2 &&
+ session_ok
+'
+
+cat >todotest1 <<EOF
+patch patchB # write 1 into file1
+pick H # generate file5
+mark :1
+patch patchC # generate file2
+squash I # generate file6
+patch patchD # write 2 into file1
+ref refs/tags/CID
+mark :2
+reset :1 # reset to new H
+patch patchD # write 2 into file1
+squash CE # generate file2 and file3
+ref refs/tags/DCE
+merge :2 # merge :2 into HEAD
+patch patchF # generate file4
+EOF
+
+test_expect_success 'all insns work without options' '
+ git checkout A &&
+ next_session squashCI &&
+ no_marks_set &&
+ git sequencer todotest1 &&
+ no_marks_set &&
+ test "$(git show HEAD:file1)" = "2" &&
+ test -z "$(git show HEAD:file2)" &&
+ test -z "$(git show HEAD:file3)" &&
+ test -z "$(git show HEAD:file4)" &&
+ test -z "$(git show HEAD:file5)" &&
+ test -z "$(git show HEAD:file6)" &&
+ echo "$(git rev-parse DCE)" >expected &&
+ echo "$(git rev-parse CID)" >>expected &&
+ git cat-file commit HEAD^ | sed -n -e "s/^parent //p" >actual &&
+ test_cmp expected actual &&
+ session_ok
+'
+
+cat >todotest1 <<EOF
+merge --standard DCE
+EOF
+
+echo "Merge DCE into HEAD" >expected1
+
+test_expect_success 'merge --standard works' '
+ git checkout CID &&
+ git sequencer todotest1 &&
+ expect_msg HEAD expected1 &&
+ session_ok
+'
+
+cat >todotest1 <<EOF
+merge --standard --message="foo" DCE
+EOF
+
+
+test_expect_success 'merge --standard --message="foo" is conflict' '
+ git checkout CID &&
+ expect_conflict git sequencer todotest1 &&
+ git sequencer --abort &&
+ session_ok
+'
+
+for command in 'pick ' 'patch patch' 'squash ' 'merge --standard '
+do
+ cat >todotest1 <<EOF
+patch patchB # 1 into file1
+${command}G # 3 into file1
+patch -3 patchF # empty file4
+EOF
+
+ test_expect_success "conflict test: ${command%% *} and --abort" '
+ git checkout A &&
+ expect_conflict git sequencer todotest1 &&
+ session_ok &&
+ test -d "$SEQDIR" &&
+ git sequencer --abort &&
+ session_ok &&
+ test $(git rev-parse HEAD) = $(git rev-parse A)
+ '
+
+ test_expect_success "conflict test: ${command%% *} and --continue" '
+ git checkout A &&
+ expect_conflict git sequencer todotest1 &&
+ session_ok &&
+ test -d "$SEQDIR" &&
+ ## XXX: It would be perfect if we could remove the if
+ { if test "${command%% *}" != "patch"
+ then grep "^<<<<<<<" file1 ; fi } &&
+ echo 3 >file1 &&
+ git add file1 &&
+ next_session nochange &&
+ git sequencer --continue &&
+ session_ok &&
+ ! test -d "$SEQDIR" &&
+ test "$(git show HEAD:file1)" = "3" &&
+ test -f file4
+ '
+
+ test_expect_success "conflict test: ${command%% *} and --skip" '
+ git checkout A &&
+ expect_conflict git sequencer todotest1 &&
+ session_ok &&
+ test -d "$SEQDIR" &&
+ git sequencer --skip &&
+ session_ok &&
+ ! test -d "$SEQDIR" &&
+ test "$(git show HEAD:file1)" = "1" &&
+ test -f file4
+ '
+done
+
+echo 'file5-gen' >commitmsg
+
+cat >todotest1 <<EOF
+patch --signoff patchB
+pause
+pick --author="$yet_another" --file="commitmsg" --signoff H
+mark :1
+patch --message="file2-gen" patchC
+squash --signoff --author="$yet_another" I
+pause
+patch --message="echo 2 >file1" patchD
+mark :2
+reset :1
+patch --author="$yet_another" patchD
+squash --signoff --message="generate file[23]" CE
+merge --signoff --message="test merge" --author="$yet_another" :2
+pause
+ref refs/tags/a_merge
+patch --message="Generate file4 and write 23 into it" patchF.raw
+pause
+pick I
+EOF
+
+cat >expected1 <<EOF
+write 1 into file
+
+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+EOF
+
+test_expect_success 'insns work with options and another author 1' '
+ git checkout A &&
+ no_marks_set &&
+
+ # patch --signoff patchB # write 1 into file1
+ # pause
+ expect_continue git sequencer todotest1 &&
+ test "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
+ "$(git cat-file commit HEAD | grep "^Signed-off-by")" &&
+ expect_author HEAD "$orig_author" &&
+ test -d "$SEQDIR" &&
+ session_ok
+'
+
+cat >expected1 <<EOF
+file5-gen
+
+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+EOF
+
+cat >expected2 <<EOF
+file2-gen
+
+generate empty file6
+
+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+EOF
+
+test_expect_success 'insns work with options and another author 2' '
+ : >file7 &&
+ git add file7 &&
+ next_session nochange &&
+ git commit --amend &&
+ session_ok &&
+
+ next_session nochange &&
+ expect_continue git sequencer --continue &&
+ session_ok &&
+
+ # amended commit
+ test "Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>" = \
+ "$(git cat-file commit HEAD^^ | grep "^Signed-off-by")" &&
+ expect_author HEAD^^ "$orig_author" &&
+ test -z "$(git show HEAD:file7)" &&
+
+ # pick --author="$yet_another" --file="commitmsg" --signoff H
+ expect_author HEAD^ "$yet_another" &&
+ expect_msg HEAD^ expected1 &&
+ test -z "$(git show HEAD:file5)" &&
+
+ # mark :1
+ test "$(git rev-parse "$SEQMARK/1")" = "$(git rev-parse HEAD^)" &&
+
+ # patch --message="file2-gen" patchC
+ # squash --signoff --author="$yet_another" I # generate file6
+ # pause
+ test -z "$(git show HEAD:file2)" &&
+ test -z "$(git show HEAD:file6)" &&
+ git ls-files | grep "^file2" &&
+ git ls-files | grep "^file6" &&
+ expect_msg HEAD expected2 &&
+ expect_author HEAD "$yet_another"
+'
+
+echo 'echo 2 >file1' >expected1
+
+cat >expected2 <<EOF
+generate file[23]
+
+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+EOF
+
+cat >expected3 <<EOF
+test merge
+
+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+EOF
+
+cat >expected4 <<EOF
+file1
+file2
+file3
+file5
+file6
+file7
+EOF
+
+test_expect_success 'insns work with options and another author 3' '
+ # do not change anything
+ expect_continue git sequencer --continue &&
+ session_ok &&
+
+ # patch --message="echo 2 >file1" patchD
+ # mark :2
+ commit="$(git rev-parse --verify "$SEQMARK/2")" &&
+ expect_author "$commit" "$orig_author" &&
+ expect_msg "$commit" expected1 &&
+
+ # reset :1
+ # patch --author="$yet_another" patchD # write 2 into file1
+ # squash --signoff --message="generate file[23]" CE
+ expect_author HEAD^ "$yet_another" &&
+ expect_msg HEAD^ expected2 &&
+
+ # merge --signoff --message="test merge" --author="$yet_another" :2
+ # pause
+ expect_author HEAD "$yet_another" &&
+ expect_msg HEAD expected3 &&
+ git ls-files >actual &&
+ test_cmp expected4 actual
+'
+
+cat >expected_merge <<EOF
+cleanup merge
+
+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+EOF
+
+echo 'Generate file4 and write 23 into it' >expected2
+
+test_expect_success 'insns work with options and another author 4' '
+ git rm file5 file6 file7 &&
+ next_session merge2 &&
+ expect_continue git sequencer --continue &&
+ session_ok &&
+
+ # ref refs/tags/a_merge
+ expect_author a_merge "$yet_another" &&
+ expect_msg a_merge expected_merge &&
+
+ # patch --message="Generate file4 and write 23 into it" patchF.raw
+ # pause
+ git ls-files | grep "^file4" &&
+ echo 23 >file4 &&
+ git add file4 &&
+ next_session nochange &&
+ git sequencer --continue &&
+ session_ok &&
+ no_marks_set &&
+ test "$(git show HEAD:file1)" = "2" &&
+ test "$(git show HEAD:file4)" = "23" &&
+ expect_msg HEAD^ expected2 &&
+ expect_author HEAD^ "$GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL>" &&
+
+ # pick I
+ test -z "$(git show HEAD:file6)" &&
+ git ls-files | grep "^file6" &&
+ session_ok
+'
+
+# almost the same to test --quiet
+cat >todotest1 <<EOF
+patch patchB
+pick H
+mark :1
+patch patchC
+squash --message="a squash" I
+patch patchD
+mark :2
+reset :1
+patch patchD
+squash --message="another squash" CE
+merge --message="test merge" :2
+pause
+patch patchF
+EOF
+
+test_expect_failure '--quiet works' '
+ git checkout A &&
+ expect_continue git sequencer --quiet todotest1 >actual &&
+ session_ok &&
+ ! test -s actual
+'
+
+test_expect_failure '--quiet works on continue' '
+ git sequencer --continue >>actual &&
+ session_ok &&
+ ! test -s actual
+'
+
+echo 'merge --strategy=ours --reuse-commit=a_merge branch1 branch2 CE CID' >todotest1
+
+test_expect_success 'merge multiple branches and --reuse-commit works' '
+ git checkout -b merge-multiple master &&
+ git sequencer todotest1 &&
+ session_ok &&
+ expect_msg HEAD expected_merge &&
+ git rev-parse HEAD^ >expected &&
+ git rev-parse branch1 >>expected &&
+ git rev-parse branch2 >>expected &&
+ git rev-parse CE >>expected &&
+ git rev-parse CID >>expected &&
+ git cat-file commit HEAD | sed -n -e "s/^parent //p" >actual &&
+ test_cmp expected actual &&
+ ! test -f file6
+'
+
+echo 'pick --mainline=5 merge-multiple' >todotest1
+
+test_expect_success 'pick --mainline works' '
+ git checkout -b mainline CID &&
+ git sequencer todotest1 &&
+ session_ok &&
+ expect_msg HEAD expected_merge &&
+ ! test -f file6 &&
+ test -f file3 &&
+ test -f file2 &&
+ test "$(git show HEAD:file1)" = 2
+'
+
+cat >todotest1 <<EOF
+pick C # file2
+mark :1
+patch patchB # write 1 into file1
+patch patchD # write 2 into file1
+pick I # file6
+squash --message="2 in file1 and file6 exists" --signoff --from :1
+EOF
+
+cat >expected1 <<EOF
+2 in file1 and file6 exists
+
+Signed-off-by: $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>
+EOF
+
+test_expect_success 'squash --from works' '
+ git checkout A &&
+ git sequencer <todotest1 &&
+ session_ok &&
+ test "$(git rev-parse A)" = "$(git rev-parse HEAD~2)" &&
+ test "$(git show HEAD:file1)" = "2" &&
+ test -z "$(git show HEAD:file6)" &&
+ expect_msg HEAD expected1
+'
+
+cat >todotest1 <<EOF
+patch patchB # write 1 into file1
+pick H # generate file5
+mark :1
+patch patchC # generate file2
+squash --message="file5" I # generate file6
+patch patchD # write 2 into file1
+mark :2
+reset :1 # reset to new H
+patch patchD # write 2 into file1
+squash --message="CE" CE # generate file2 and file3
+merge --standard :2 # merge :2 into HEAD
+patch patchF # generate file4
+EOF
+cp todotest1 todotest2
+cat todotest1 | sed -e 's/^\(patch\|pick\|squash\|merge\) /&--edit /' >todotest3
+echo 'squash --message="doesnt work either" --from :1' >>todotest1
+echo 'squash --include-merges --message="stupid" --from :1' >>todotest2
+
+test_expect_success 'squash --from conflicts with merge in between' '
+ git checkout A &&
+ expect_conflict git sequencer todotest1 &&
+ git sequencer --abort &&
+ session_ok &&
+ ! test -d "$SEQDIR"
+'
+
+test_expect_success 'squash --include-merges --from succeeds with merge in between' '
+ git checkout A &&
+ git sequencer todotest2 &&
+ session_ok &&
+ test "$(git rev-parse HEAD~3)" = "$(git rev-parse A)"
+'
+
+test_expect_success 'patch|pick|squash|merge --edit works' '
+ git checkout A &&
+ next_session editX &&
+ git sequencer todotest3 &&
+ session_ok
+'
+
+cat >todotest1 <<EOF
+patch patchB
+pause
+EOF
+
+test_expect_success 'batch mode fails on pause insn' '
+ git checkout A &&
+ expect_fail git sequencer --batch todotest1 &&
+ session_ok &&
+ ! test -d "$SEQDIR"
+'
+
+cat >todotest1 <<EOF
+patch patchB
+pick G
+EOF
+
+test_expect_success 'batch mode fails on conflict' '
+ git checkout A &&
+ expect_fail git sequencer --batch <todotest1 &&
+ session_ok &&
+ ! test -d "$SEQDIR" &&
+ test -z "$(git show HEAD:file1)"
+'
+
+cat >todotest1 <<EOF
+patch patchB
+pause
+EOF
+
+test_expect_success '--caller works' '
+ git checkout A &&
+ expect_continue git sequencer \
+ --caller="this works|abrt||skip" todotest1 &&
+ expect_fail git sequencer --abort &&
+ expect_fail git sequencer --skip &&
+ git sequencer --continue &&
+ session_ok
+'
+
+test_done
--
1.5.6.3.391.ge45b
^ permalink raw reply related
* [PATCH 2/3] Add git-sequencer documentation
From: Stephan Beyer @ 2008-07-16 20:45 UTC (permalink / raw)
To: git; +Cc: Stephan Beyer, Daniel Barkalow, Christian Couder, Junio C Hamano
In-Reply-To: <cfa3b96d13488d57caf8b758367cdf0679126462.1216233914.git.s-beyer@gmx.net>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
Documentation/git-sequencer.txt | 673 +++++++++++++++++++++++++++++++++++++++
1 files changed, 673 insertions(+), 0 deletions(-)
create mode 100644 Documentation/git-sequencer.txt
diff --git a/Documentation/git-sequencer.txt b/Documentation/git-sequencer.txt
new file mode 100644
index 0000000..8a701c4
--- /dev/null
+++ b/Documentation/git-sequencer.txt
@@ -0,0 +1,673 @@
+git-sequencer(1)
+================
+
+NAME
+----
+git-sequencer - Execute a sequence of git instructions
+
+SYNOPSIS
+--------
+[verse]
+'git sequencer' [--batch] [--onto=<base>]
+ [--verbose | --no-advice | --quiet]
+ [--] [<file>]
+'git sequencer' --continue | --skip | --abort | --edit | --status
+
+
+DESCRIPTION
+-----------
+Executes a sequence of git instructions to HEAD or `<base>`.
+The sequence is given by `<file>` or standard input.
+Also see 'TODO FILE FORMAT' below.
+
+Before doing anything, the TODO file is checked for correct syntax
+and sanity.
+
+In case of a conflict or request in the TODO file, 'git-sequencer' will
+pause. On conflict you can use 'git-diff' to locate the markers (`<<<<<<<`)
+and make edits to resolve the conflict.
+
+For each file you edit, you need to tell git the changes by doing
+
+ git add <file>
+
+After resolving the conflict manually and updating the index with the
+desired resolution, you can continue the sequencing process with
+
+ git sequencer --continue
+
+Alternatively, you can undo the 'git-sequencer' progress with
+
+ git sequencer --abort
+
+or skip the current instruction with
+
+ git sequencer --skip
+
+or correct the TODO file with
+
+ git sequencer --edit
+
+During pauses or when finished with the sequencing task, the current
+HEAD will always be the result of the last processed instruction.
+
+
+OPTIONS
+-------
+<file>::
+ Filename of the TODO file. If omitted, standard input is used.
+ See 'TODO FILE FORMAT' below.
+
+-B::
+--batch::
+ Run in batch mode. If unexpected user intervention is needed
+ (e.g. a conflict or the need to run an editor), 'git-sequencer' fails.
++
+Note that the sanity check fails, if you use this option
+and an instruction like `edit` or `pause` is in the TODO file.
+
+--onto=<base>::
+ Checkout given commit or branch before sequencing.
+ If you provide a branch, sequencer will make the provided
+ changes on the branch, i.e. the branch will be changed.
+
+--continue::
+ Restart the sequencing process after having resolved a merge conflict.
+
+--abort::
+ Restore the original branch and abort the sequence operation.
+
+--skip::
+ Restart the sequencing process by skipping the current instruction.
+
+--status::
+ Show the current status of 'git-sequencer' and what
+ operations can be done to change that status.
+
+--edit::
+ Invoke editor to edit the unprocessed part of the TODO file.
++
+The file is syntax- and sanity-checked afterwards, so that you can
+safely run `git sequencer --skip` or `--continue` after editing.
+If you nonetheless noticed that you made a mistake, you can
+overwrite `.git/sequencer/todo` with `.git/sequencer/todo.old` and
+rerun `git sequencer --edit`.
++
+If the check fails you are prompted if you want to correct your
+changes, edit again, cancel editing or really want to save.
+
+--no-advice::
+ Suppress advice on intentional and unintentional pauses.
+
+-q::
+--quiet::
+ Suppress output. Implies `--no-advice`.
+ (Not yet implemented.)
+
+-v::
+--verbose::
+ Be more verbose.
+
+
+NOTES
+-----
+
+When sequencing, it is possible, that you are changing the history of
+a branch in a way that can cause problems for anyone who already has
+a copy of the branch in their repository and tries to pull updates from
+you. You should understand the implications of using 'git-sequencer' on
+a repository that you share.
+
+'git-sequencer' will usually be called by another git porcelain, like
+linkgit:git-am[1] or linkgit:git-rebase[1].
+
+
+TODO FILE FORMAT
+----------------
+
+The TODO file contains basically one instruction per line.
+
+Blank lines will be ignored.
+All characters after a `#` character will be ignored until the end of a line.
+
+The following instructions can be used:
+
+
+edit <commit>::
+ Pick a commit and pause the sequencer process to let you
+ make changes.
++
+This is a short form for `pick <commit> and `pause` on separate lines.
+
+
+mark <mark>::
+ Set a symbolic mark for the last commit.
+ `<mark>` is an unsigned integer starting at 1 and
+ prefixed with a colon, e.g. `:1`.
++
+The marks can help if you want to refer to commits that you
+created during the sequencer process, e.g. if you want to
+merge such a commit.
++
+The set marks are removed after the sequencer has completed.
+
+
+merge [options] <commit-ish1> <commit-ish2> ... <commit-ishN>::
+ Merge commits into HEAD.
++
+You can refer to a commit by a mark.
++
+If you do not provide a commit message (using `-F`, `-m`, `-C`, `-M`,
+or `--standard`), an editor will be invoked.
++
+See the following list and 'GENERAL OPTIONS' for values of `options`:
+
+ --standard;;
+ Generate a commit message like 'Merge ... into HEAD'.
+ See also linkgit:git-fmt-merge-msg[1].
+
+ -s <strategy>;;
+ --strategy=<strategy>;;
+ Use the given merge strategy.
+ See also linkgit:git-merge[1].
+
+
+pick [options] <commit>::
+ Pick (see linkgit:git-cherry-pick[1]) a commit.
+ Sequencer will pause on conflicts.
++
+See the following list and 'GENERAL OPTIONS' for values of `options`:
+
+ -R;;
+ --reverse;;
+ Revert the changes introduced by pick <commit>.
+
+ --mainline=<n>;;
+ Allow you to pick merge commits by specifying the
+ parent number (beginning from 1) to let sequencer
+ replay the changes relative to the specified parent.
+ +
+This option does not work together with `-R`.
+
+
+patch [options] <file>::
+ If file `<file>` is a pure (diff) patch, then apply the patch.
+ If no `--message` option is given, an editor will
+ be invoked to enter a commit message.
++
+If `<file>` is a linkgit:git-format-patch[1]-formatted patch,
+then the patch will be commited.
++
+See the following list and 'GENERAL OPTIONS' for values of `options`:
+
+ -3;;
+ --3way;;
+ When the patch does not apply cleanly, fall back on
+ 3-way merge, if the patch records the identity of blobs
+ it is supposed to apply to, and we have those blobs
+ available locally.
+
+ -k;;
+ Pass `-k` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
+
+ -n;;
+ Pass `-n` flag to 'git-mailinfo' (see linkgit:git-mailinfo[1]).
+
+ --exclude=<path-pattern>;;
+ Do not apply changes to files matching the given path pattern.
+ This can be useful when importing patchsets, where you want to
+ exclude certain files or directories.
+
+ -R;;
+ --reverse;;
+ Apply the patch in reverse.
+
+ --no-add;;
+ When applying a patch, ignore additions made by the
+ patch. This can be used to extract the common part between
+ two files by first running 'diff' on them and applying
+ the result with this option, which would apply the
+ deletion part but not addition part.
+
+ --whitespace=<action>;;
+ Specify behavior on whitespace errors.
+ See linkgit:git-apply[1] for a detailed description.
+
+ --context=<n>;;
+ Ensure at least <n> lines of surrounding context match before
+ and after each change. When fewer lines of surrounding
+ context exist they all must match. By default no context is
+ ever ignored.
+
+ --inaccurate-eof;;
+ Under certain circumstances, some versions of 'diff' do not
+ correctly detect a missing new-line at the end of the file.
+ As a result, patches created by such 'diff' programs do not
+ record incomplete lines correctly.
+ This option adds support for applying such patches by
+ working around this bug.
+
+ -p<n>;;
+ Remove <n> leading slashes from traditional diff paths.
+ The default is 1.
+
+ --unidiff-zero;;
+ By default, 'git-apply' expects that the patch being
+ applied is a unified diff with at least one line of context.
+ This provides good safety measures, but breaks down when
+ applying a diff generated with --unified=0. To bypass these
+ checks use this option.
+
+
+pause::
+ Pause the sequencer process to let you manually make changes.
+ For example, you can re-edit the done commit, split a commit,
+ fix bugs or typos, or make further commits on top of HEAD before
+ continuing.
++
+After you have finished your changes and added them to the index,
+invoke `git sequencer --continue`.
+If you only want to edit the last commit message with an editor,
+run `git commit --amend` (see linkgit:git-commit[1]) before saying
+`--continue`.
+
+
+ref <ref>::
+ Set ref `<ref>` to the current HEAD, see also
+ linkgit:git-update-ref[1].
+
+
+reset <commit-ish>::
+ Go back (see linkgit:git-reset[1] `--hard`) to commit `<commit-ish>`.
+ `<commit-ish>` can also be given by a mark, if prefixed with a colon.
+
+
+squash [options] <commit>::
+ Add the changes introduced by `<commit>` to the last commit.
++
+See 'GENERAL OPTIONS' for values of `options`.
+
+squash [options] --from <mark>::
+ Squash all commits from the given mark into one commit.
+ There must not be any `merge` instructions between the
+ `mark` instruction and this `squash --from` instruction.
++
+See the following list and 'GENERAL OPTIONS' for values of `options`:
+
+ --collect-signoffs;;
+ Collect the Signed-off-by: lines of each commit and
+ add them to the squashed commit message.
+ (Not yet implemented.)
+
+ --include-merges;;
+ Sanity check does not fail if you have merges
+ between HEAD and <mark>.
+
+
+run [--dir=<path>] [--] <cmd> <args>...::
+ Run command `<cmd>` with arguments `<args>`.
+ Pause (conflict-like) if exit status is non-zero.
++
+If `<path>` is set, sequencer will change directory to `<path>`
+before running the command and change back after exit.
+
+
+GENERAL OPTIONS
+---------------
+
+Besides some special options, the instructions
+`patch`, `merge`, `pick`, `squash` take the following general options:
+
+--author=<author>::
+ Override the author name and e-mail address used in the commit.
+ Use `A U Thor <author@example.com>` format.
+
+-C <commit-ish>::
+--reuse-commit=<commit-ish>::
+ Reuse message and authorship data from specified commit.
+
+-M <commit-ish>
+--reuse-message=<commit-ish>::
+ Reuse message from specified commit.
+ Note, that only the commit message is reused
+ and not the authorship information.
+
+-F <file>::
+--file=<file>::
+ Take the commit message from the given file.
+
+-m <msg>::
+--message=<msg>::
+ Use the given `<msg>` as the commit message.
+
+--signoff::
+ Add `Signed-off-by:` line to the commit message (if not yet there),
+ using the committer identity of yourself.
+
+-e::
+--edit::
+ Regardless what commit message options are given,
+ invoke the editor to allow editing of the commit message.
+
+
+RETURN VALUES
+-------------
+
+'git-sequencer' returns:
+
+* `0`, if 'git-sequencer' successfully completed all the instructions
+ in the TODO file or successfully aborted after
+ `git sequencer --abort`,
+* `2`, on user-requested pausing, e.g.
+ when using the `edit` instruction.
+* `3`, on pauses that are not requested, e.g.
+ when there are conflicts to resolve
+ or errors in the TODO file.
+* any other value on error, e.g.
+ running 'git-sequencer' on a bare repository.
+
+
+EXAMPLES
+--------
+
+Here are some examples that shall ease the start with the TODO
+file format.
+Make sure you have understood the `pick` and perhaps the `patch` command.
+Those will not be explained further.
+
+Manually editing and adding commits
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Sequencer allows manual intervention in between.
+This can be useful to
+
+* check if everything has gone right so far,
+
+* split commits,
+
+* edit changes and/or commit messages, or
+
+* add further manual commits on top of the current one.
+
+If you want to do one of this, either change `pick` to `edit`, or
+add a `pause` line after the specific instruction.
+
+Note that if you only want to edit the commit message in an
+editor, just use the `--edit` option of your `pick` or `patch`
+instruction.
+
+`HEAD` refers to the last commit being done by sequencer.
+So if you want to split a commit, repeat something like
+
+------------
+$ git reset HEAD^ # Reset index to HEAD^, but keep working tree
+ # HEAD is the last commit being done by sequencer
+$ git add -p # Add changes interactively to the index, and/or
+$ git add file1 # Add changes from file1 to the index
+$ git commit # Commit staged changes
+------------
+
+until you have no changes to commit, and then run
+
+------------
+$ git sequencer --continue # Continue sequencer process
+------------
+
+Be aware that if there are still staged changes,
+'git-sequencer' will add those changes to the last commit being done.
+
+
+Squashing commits
+~~~~~~~~~~~~~~~~~
+
+Squashing commits means putting the changes of many commits into one.
+If you have two commits `abcdef1` and `fa1afe1` and you want to squash them,
+feed 'git-sequencer' with a TODO file like:
+
+------------
+pick abcdef1
+squash fa1afe1
+------------
+
+Squash will concatenate the commit messages of `abcdef1` and `fa1afe1` and
+invoke an editor so that you can edit them.
+Perhaps you just want to reuse the commit message of `abcdef1` and
+add a signoff. Then use:
+
+------------
+pick abcdef1
+squash -C abcdef1 --signoff fa1afe1
+------------
+
+You can also squash more than two commits.
+Basically you can do:
+
+------------
+pick A
+squash B
+squash C
+squash D
+squash --message "Make indentation consistent" --signoff E
+------------
+
+If somebody sent you a patch that you have not yet applied and you want
+to apply it and squash it, or if you have a `pick <commit>` list generated
+with something like
+
+------------
+$ git rev-list --no-merges --reverse A^..E | sed -e 's/^/pick /'`
+------------
+
+you can use the `mark` and `squash --from` instructions to
+squash all commits between them into one:
+
+------------
+mark :0
+pick A
+pick B
+pick C
+pick D
+pick E
+squash --message "Make indentation consistent" --signoff --from :0
+------------
+
+
+Branching and Merging
+~~~~~~~~~~~~~~~~~~~~~
+
+Merging branches can easily be done using the `merge` instruction.
+For an example, it is more interesting to branch, pick some commits
+and merge. Imagine you want to 'copy' this onto the current branch:
+
+------------
+ ...--A1--A2--A3--A4--A5---MA-A6 refs/heads/old
+ | \ /
+ | C1--MC--C2 refs/heads/topic
+ \ /
+ B1--B2--B3
+------------
+
+You want the copy to look exactly like this, except that you
+are not on branch `old`, and you want to call the copy of `topic`
+simply `topic2`.
+Here is a way to achieve this:
+
+------------
+pick A1
+mark :0 # remember this to pick further commits on trunk A
+
+pick B1 # pick commits for trunk B
+pick B2
+pick B3
+mark :1 # remember this for merge
+# Why not just merge B3 later?
+# Then you would merge the original B3 and not the copy.
+# But in this example you want to merge the copy of B3.
+
+reset :0 # go back to the copy of A1
+pick A2 # go on picking the commits of trunk A
+pick A3
+mark :2 # remember this to pick further commits on trunk A
+
+pick C1 # pick commits for trunk C
+merge -C MC :1 # merge trunk B
+pick C2
+ref refs/heads/topic2 # create branch for the C trunk
+
+reset :2 # go back to last commit of trunk A (copy of A3)
+pick A4 # go on picking the commits of trunk A
+pick A5
+merge --standard topic2 # merge trunk C
+pick A6
+------------
+
+
+Proper handling of conflicts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+First of all, you are encouraged to use linkgit:git-rerere[1]:
+
+------------
+$ git config rerere.enabled true # enable rerere
+------------
+
+Sequencer invokes 'git-rerere' automatically on conflict.
+
+If you experience conflicts, try
+
+------------
+$ git diff # Show conflicting code
+$ git status # Show conflicting files
+------------
+
+Then fix these conflicts using your editor and run
+
+------------
+$ git add file1 file2 file3 # Add modified files to the index
+$ git status # Make sure working tree is clean
+$ git sequencer --continue # Continue sequencer process
+------------
+
+Now assume a conflict happens because you have unproperly edited
+the TODO file.
+
+Imagine your initial TODO file was:
+
+------------
+pick A
+pick C
+pick D
+------------
+
+But you wanted to pick B before C, and now you have this conflict on
+picking C. You may first have a look at:
+
+------------
+$ git sequencer --status
+------------
+
+This will show you, what has been done, in what step the conflict
+happened and what is still to do, like this:
+
+------------
+Already done (or tried):
+ pick A
+ pick C
+
+Interrupted by conflict at
+ pick C
+
+Still to do:
+ pick D
+
+To abort & restore, invoke:
+ git sequencer --abort
+To continue, invoke:
+ git sequencer --continue
+To skip the current instruction, invoke:
+ git sequencer --skip
+------------
+
+A good way to solve that situation is running
+
+------------
+$ git sequencer --edit
+------------
+
+and change the file to:
+
+------------
+pick B
+pick C
+pick D
+------------
+
+Save the file, and invoke:
+
+------------
+$ git sequencer --skip
+------------
+
+Then the conflict-ridden `pick C` will be skipped and B is picked,
+before C will again be picked.
+
+
+Running tests
+~~~~~~~~~~~~~
+
+Imagine you have test programs within a `tests/` directory in your working
+tree. But before running your test programs, you have to invoke `make` in
+the root directory of the working tree to compile your project.
+
+If the commit policy of your project says that after every commit the
+software must be able to compile and the test suite must pass, you
+are required to check this after every pick.
+
+This example shows how 'git-sequencer' can assist you:
+
+------------
+pick A # Fix foo
+run make
+run --dir=tests ./test-foo
+pick B # Extend bar
+run make
+run --dir tests -- ./test-bar --expensive-tests
+pick C
+run make
+run --dir tests make tests
+------------
+
+Sequencer will be paused, when a run fails (i.e. on non-zero exit status).
+Then it is your turn to fix the problem and make the tests pass.
+
+Note, that on `git sequencer --continue`, 'git-sequencer' will not
+repeat the failed `run` instruction.
+
+
+SEE ALSO
+--------
+
+linkgit:git-add[1],
+linkgit:git-am[1],
+linkgit:git-cherry-pick[1],
+linkgit:git-commit[1],
+linkgit:git-fmt-merge-msg[1],
+linkgit:git-format-patch[1],
+linkgit:git-rebase[1],
+linkgit:git-rerere[1],
+linkgit:git-reset[1],
+linkgit:git-update-ref[1]
+
+
+Authors
+-------
+Written by Stephan Beyer <s-beyer@gmx.net>.
+
+
+Documentation
+-------------
+Documentation by Stephan Beyer and the git-list <git@vger.kernel.org>.
+
+GIT
+---
+Part of the linkgit:git[1] suite
--
1.5.6.3.391.ge45b
^ permalink raw reply related
* [PATCH (GIT-GUI) 2/3] Kill the blame back-end on window close.
From: Alexander Gavrilov @ 2008-07-16 20:48 UTC (permalink / raw)
To: git; +Cc: Shawn O. Pearce
In-Reply-To: <200807170043.49016.angavrilov@gmail.com>
Currently 'git-gui blame' does not kill its back-end
process, hoping that it will die anyway when the pipe
is closed. However, in some cases the process works
for a long time without producing any output. This
behavior results in a runaway CPU hog.
Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
The -f flag is necessary for msysgit.
For this fix I submitted to msysgit a patch that includes
a Cygwin-compatible kill.exe in the installer.
-- Alexander
git-gui.sh | 14 ++++++++++++++
lib/blame.tcl | 16 ++++++++++++----
2 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index b1ed0ec..83e2645 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -497,6 +497,20 @@ proc githook_read {hook_name args} {
return {}
}
+proc kill_file_process {fd} {
+ set process [pid $fd]
+
+ catch {
+ if {[is_Windows]} {
+ # Use a Cygwin-specific flag to allow killing
+ # native Windows processes
+ exec kill -f $process
+ } else {
+ exec kill $process
+ }
+ }
+}
+
proc sq {value} {
regsub -all ' $value "'\\''" value
return "'$value'"
diff --git a/lib/blame.tcl b/lib/blame.tcl
index 192505d..2c19048 100644
--- a/lib/blame.tcl
+++ b/lib/blame.tcl
@@ -326,19 +326,27 @@ constructor new {i_commit i_path} {
bind $w.file_pane <Configure> \
"if {{$w.file_pane} eq {%W}} {[cb _resize %h]}"
+ wm protocol $top WM_DELETE_WINDOW "destroy $top"
+ bind $top <Destroy> [cb _kill]
+
_load $this {}
}
+method _kill {} {
+ if {$current_fd ne {}} {
+ kill_file_process $current_fd
+ catch {close $current_fd}
+ set current_fd {}
+ }
+}
+
method _load {jump} {
variable group_colors
_hide_tooltip $this
if {$total_lines != 0 || $current_fd ne {}} {
- if {$current_fd ne {}} {
- catch {close $current_fd}
- set current_fd {}
- }
+ _kill $this
foreach i $w_columns {
$i conf -state normal
--
1.5.6.3.17.g3f148
^ permalink raw reply related
* [PATCH (GIT-GUI) 3/3] Add a menu item to invoke full copy detection in blame.
From: Alexander Gavrilov @ 2008-07-16 20:51 UTC (permalink / raw)
To: git; +Cc: Shawn O. Pearce
In-Reply-To: <200807170048.08909.angavrilov@gmail.com>
Add a context menu item to invoke blame -C -C -C on a chunk
of the file. The results are used to update the 'original
location' column of the blame display.
The chunk is computed as the smallest line range that covers
both the 'last change' and 'original location' ranges of the
line that was clicked to open the menu.
Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
This is my most complex Tcl/Tk code so far, so I might have
done some stupid things.
-- Alexander
lib/blame.tcl | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/lib/blame.tcl b/lib/blame.tcl
index 2c19048..b6e42cb 100644
--- a/lib/blame.tcl
+++ b/lib/blame.tcl
@@ -256,6 +256,9 @@ constructor new {i_commit i_path} {
$w.ctxm add command \
-label [mc "Copy Commit"] \
-command [cb _copycommit]
+ $w.ctxm add command \
+ -label [mc "Do Full Copy Detection"] \
+ -command [cb _fullcopyblame]
foreach i $w_columns {
for {set g 0} {$g < [llength $group_colors]} {incr g} {
@@ -708,6 +711,72 @@ method _read_blame {fd cur_w cur_d} {
}
} ifdeleted { catch {close $fd} }
+method _find_commit_bound {data_list start_idx delta} {
+ upvar #0 $data_list line_data
+ set pos $start_idx
+ set limit [expr {[llength $line_data] - 1}]
+ set base_commit [lindex $line_data $pos 0]
+
+ while {$pos > 0 && $pos < $limit} {
+ set new_pos [expr {$pos + $delta}]
+ if {[lindex $line_data $new_pos 0] ne $base_commit} {
+ return $pos
+ }
+
+ set pos $new_pos
+ }
+
+ return $pos
+}
+
+method _fullcopyblame {} {
+ if {$current_fd ne {}} {
+ tk_messageBox \
+ -icon error \
+ -type ok \
+ -title [mc "Busy"] \
+ -message [mc "Annotation process is already running."]
+
+ return
+ }
+
+ # Switches for original location detection
+ set threshold [get_config gui.copyblamethreshold]
+ set original_options [list -C -C "-C$threshold"]
+
+ if {[git-version >= 1.5.3]} {
+ lappend original_options -w ; # ignore indentation changes
+ }
+
+ # Find the line range
+ set pos @$::cursorX,$::cursorY
+ set lno [lindex [split [$::cursorW index $pos] .] 0]
+ set min_amov_lno [_find_commit_bound $this @amov_data $lno -1]
+ set max_amov_lno [_find_commit_bound $this @amov_data $lno 1]
+ set min_asim_lno [_find_commit_bound $this @asim_data $lno -1]
+ set max_asim_lno [_find_commit_bound $this @asim_data $lno 1]
+
+ if {$min_asim_lno < $min_amov_lno} {
+ set min_amov_lno $min_asim_lno
+ }
+
+ if {$max_asim_lno > $max_amov_lno} {
+ set max_amov_lno $max_asim_lno
+ }
+
+ lappend original_options -L "$min_amov_lno,$max_amov_lno"
+
+ # Clear lines
+ for {set i $min_amov_lno} {$i <= $max_amov_lno} {incr i} {
+ lset amov_data $i [list ]
+ }
+
+ # Start the back-end process
+ _exec_blame $this $w_amov @amov_data \
+ $original_options \
+ [mc "Running thorough copy detection..."]
+}
+
method _click {cur_w pos} {
set lno [lindex [split [$cur_w index $pos] .] 0]
_showcommit $this $cur_w $lno
--
1.5.6.3.17.g3f148
^ permalink raw reply related
* Re: Considering teaching plumbing to users harmful
From: Junio C Hamano @ 2008-07-16 20:51 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0807161804400.8950@racer>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Am I the only one who deems teaching plumbing to users ("I like it raw!
> So I teach it the same way!") harmful?
I think that justification is harmful.
More productive way to think about it is to identify cases where we _need_
to go down to combination of the plumbing commands in our daily workflow,
with today's command set. That would give us a good indication that some
Porcelain may need to be enhanced.
An example. I find myself running "git read-tree -m -u $another_state"
while redoing a series inside a "rebase -i" session to move commit
boundaries. There may need an insn that says "use that tree" instead of
"edit" and running "read-tree -m -u" by hand. This does not bother me too
much, but there probably are other examples.
Another example. I often run "git ls-files -u" while looking at which
paths are conflicting. ls-files is classified as plumbing, but it does
not bother me as much as having to see the staged long object names in
this output. Other people, however, might find it yucky, and we might
want "git merge --unmerged" or something that lists the paths (and only
paths, no stage information) that still have conflicts.
^ permalink raw reply
* Re: [PATCH] Don't cut off last character of commit descriptions.
From: Junio C Hamano @ 2008-07-16 21:11 UTC (permalink / raw)
To: David Kågedal; +Cc: git, Nikolaj Schumacher
In-Reply-To: <87k5g7fb05.fsf@lysator.liu.se>
David Kågedal <davidk@lysator.liu.se> writes:
> Nikolaj Schumacher <n_schumacher@web.de> writes:
>
>> From d485d9c86cba49671b74c7c1571a6ad7ec6d09b6 Mon Sep 17 00:00:00 2001
>> From: Nikolaj Schumacher <git@nschum.de>
>> Date: Mon, 30 Jun 2008 12:06:01 +0200
>> Subject: [PATCH] Don't cut off last character of commit descriptions.
>>
>> ---
>> contrib/emacs/git-blame.el | 2 +-
>> 1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/contrib/emacs/git-blame.el b/contrib/emacs/git-blame.el
>> index 9f92cd2..4fa70c5 100644
>> --- a/contrib/emacs/git-blame.el
>> +++ b/contrib/emacs/git-blame.el
>> @@ -381,7 +381,7 @@ See also function `git-blame-mode'."
>> "log" "-1"
>> (concat "--pretty=" git-blame-log-oneline-format)
>> hash)
>> - (buffer-substring (point-min) (1- (point-max)))))
>> + (buffer-substring (point-min) (point-max))))
>>
>> (defvar git-blame-last-identification nil)
>> (make-variable-buffer-local 'git-blame-last-identification)
>
> Yes, this should have been part of
> 24a2293ad35d567530048f0d2b0d11e0012af26d git-blame.el: show the when,
> who and what in the minibuffer. that changed from using
> --pretty=oneline to --pretty=format:... without terminating newline.
Sorry, I realize I haven't applied the patch from Nikolaj. Should I take
this as an Ack?
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: david @ 2008-07-16 21:16 UTC (permalink / raw)
To: Avery Pennarun; +Cc: Junio C Hamano, Johannes Schindelin, git
In-Reply-To: <32541b130807161151x19c20f9t91b7fb9b8c7b8c7b@mail.gmail.com>
On Wed, 16 Jul 2008, Avery Pennarun wrote:
> On 7/16/08, Junio C Hamano <gitster@pobox.com> wrote:
>> "Avery Pennarun" <apenwarr@gmail.com> writes:
>> > git diff :{1,3}:path/to/filename
>> >
>> > Which is a great command, but svn definitely makes it easier to do the
>> > same thing.
>>
>> I've never seen anybody who finds "diff :{1,3}:path" *useful*.
>
> Dunno. I use it frequently, and it works great for me. Perhaps my
> brain is just poisoned by svn.
this is exactly the point that Johannes was trying to make, by teaching
people these low-level things they get confused and scared. So he is
suggesting that everyone make an effort to avoid these (at least
initially)
David Lang
> I've never tried "git log -p --merge". I'll try it next time. This
> is certainly not common knowledge, however. (But to save Dscho the
> trouble: git usability in general is not the subject of this thread.)
>
>> > Even if you have a repo with widespread push access, git's log looks
>> > annoying compared to svn because of all the merge commits. That's a
>> > primary reason why rebase was invented, of course.
>>
>> Please don't talk nonsense if you do not know history. I invented rebase
>> primarily because I wanted to help e-mail based contributors. There is
>> nothing about merge avoidance to it.
>
> Sorry, I mixed up git-rerere and git-rebase. From git-rerere's man page:
>
> When your topic branch is long-lived, however, your topic branch would
> end up having many such "Merge from master" commits on it, which would
> unnecessarily clutter the development history. Readers of the Linux
> kernel mailing list may remember that Linus complained about such too
> frequent test merges when a subsystem maintainer asked to pull from a
> branch full of "useless merges".
>
> Nowadays, I'm pretty sure people use git-rebase to avoid this sort of
> problem (or "git pull --rebase" presumably wouldn't have appeared),
> but I can now see how git-rebase was not written *for* this problem.
>
> Anyway, my point was that git-rebase (or at least git-rerere and
> git-reset) are needed if you want to avoid a lot of merge commits.
> And, to relate it back to this thread, git-rebase cannot possibly be
> understood without understanding git internals, and git internals are
> easiest to understand by learning the plumbing.
>
> svn avoids these excess merges by default, albeit because it puts your
> working copy at risk every time you do "svn update".
>
>> You can skip merges with "git log --no-merges", just in case you didn't
>> know.
>
> Perhaps this is mostly a user education or documentation issue. I
> know about --no-merges, but it's unclear that this is really a safe
> thing to use, particularly if some of your merges have conflicts.
> Leaving them out leaves out an important part of history. Do you use
> this option yourself?
>
> Have fun,
>
> Avery
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [PATCH] Rename ".dotest/" to ".git/rebase" and ".dotest-merge" to "rebase-merge"
From: Petr Baudis @ 2008-07-16 21:27 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Junio C Hamano, René Scharfe, Stephan Beyer, Joe Fiorini,
git, Jari Aalto
In-Reply-To: <alpine.DEB.1.00.0807160315020.2841@eeepc-johanness>
Hi,
On Wed, Jul 16, 2008 at 03:15:42AM +0200, Johannes Schindelin wrote:
> On Tue, 15 Jul 2008, Junio C Hamano wrote:
>
> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> >
> > > Since the files generated and used during a rebase are never to be
> > > tracked, they should live in $GIT_DIR. While at it, avoid the rather
> > > meaningless term "dotest" to "rebase", and unhide ".dotest-merge".
> >
> > I understand moving away from .dotest/ to .git/something, but I do not
> > follow the logic of making that something to rebase at all. It is a
> > scratch area for "am" (and applymbox), isn't it?
>
> Of course, you can name it as you want. But I thought that the name
> "rebase" applies as well: the patches are rebased from somewhere else on
> top of HEAD :-)
even not considering the sequencer work, wouldn't "sequence" be a well
descriptive name?
Petr "Pasky" Baudis
^ permalink raw reply
* Re: [PATCH] rebase-i: keep old parents when preserving merges
From: Junio C Hamano @ 2008-07-16 21:36 UTC (permalink / raw)
To: Stephan Beyer; +Cc: Johannes Schindelin, git
In-Reply-To: <1216173109-11155-1-git-send-email-s-beyer@gmx.net>
Stephan Beyer <s-beyer@gmx.net> writes:
... Based on the discussion thread, here is a rewrite of the log message.
> When "rebase -i -p" tries to preserve merges of unrelated branches, it
> lost some parents:
>
> - When you have more than two parents, the commit in the new history
> ends up with fewer than expected number of parents and this breakage
> goes unnoticed;
>
> - When you are rebasing a merge with two parents and one is lost, the
> command tries to cherry-pick the original merge commit, and the command
> fails.
>
> Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
>
> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> index a35212d..0df7640 100755
> --- a/git-rebase--interactive.sh
> +++ b/git-rebase--interactive.sh
> @@ -174,6 +174,8 @@ pick_one_preserving_merges () {
> new_parents="$new_parents $new_p"
> ;;
> esac
> + else
> + new_parents="$new_parents $p"
> fi
> done
Reading the surrounding code, it makes me wonder if you also need to futz
with variables like $preserve and $fast_forward.
^ permalink raw reply
* Re: [PATCH] Rename ".dotest/" to ".git/rebase" and ".dotest-merge" to "rebase-merge"
From: Junio C Hamano @ 2008-07-16 21:44 UTC (permalink / raw)
To: Petr Baudis
Cc: Johannes Schindelin, René Scharfe, Stephan Beyer,
Joe Fiorini, git, Jari Aalto
In-Reply-To: <20080716212707.GQ32184@machine.or.cz>
Petr Baudis <pasky@suse.cz> writes:
>> Of course, you can name it as you want. But I thought that the name
>> "rebase" applies as well: the patches are rebased from somewhere else on
>> top of HEAD :-)
>
> even not considering the sequencer work, wouldn't "sequence" be a well
> descriptive name?
Heh, I did not want to become a painter, especially I already have a
rather busy plumber job, but here is my thought process:
* "rebase-merge" is used only by rebase that uses merge as the pick
mechanism;
* when $dotest is used by rebase, it is to implement the "pick" mechanism
based on applying patches. "rebase-apply" is a good parallel to
"rebase-merge" here;
* when $dotest is used by am, it is to hold the patches to be applied.
Calling the directory "rebase-apply" would be easy to understand for
somebody who does _not_ know nor care about such low-level details, too.
It is a temporary holding area that is used by the procedure to rebase a
history and the procedure to apply patches.
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Dmitry Potapov @ 2008-07-16 21:48 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0807161804400.8950@racer>
On Wed, Jul 16, 2008 at 06:21:02PM +0100, Johannes Schindelin wrote:
>
> I had the pleasure of introducing Git to a few users in the last months
> and in my opinion, restricting myself to teaching them these commands
> first helped tremendously:
>
> - clone, pull, status, add, commit, push, log
Yes, it is a good list, and I think it is very important at the
beginning to limit the number commands to 7-8, otherwise many users
may be confused. And, of course, it is better to stay away from all
command-line options at first...
>
> All of these were presented without options, to keep things simple.
>
> In particular, I refrained from giving them the "-a" option to commit.
> That seemed to help incredibly with their embracing the index as a natural
> concept (which it is).
Most things that we call as "natural" is those that we got used. Once,
you got used to it, it seems very natural, and the index is not
something that is really difficult to learn, but I don't think that
everyone may understand it fully. Some may use Git for many months and
only then suddenly discover that "git diff" does not show all
uncommitted changes, but only changes between their working directory
and the index. It may sound strange, but it happens.
> Now, it makes me really, really sad that Git has a reputation of being
> complicated, but I regularly hear from _my_ users that they do not
> understand how that came about.
I think this reputation is largely due to people who open Git user
manual, read about >100 commands, were horrified and stopped learning.
Git is a powerful and very flexible tool, thus to use it to its fullest
you may really need to learn a lot, but it does not mean that you can
use it and be much more productive than with other VCS knowing only a
small fraction of all options. Thus if you can explain to users in terms
that they understood and connect that with their workflow, users may
find Git easier to use than SVN...
>
> Am I the only one who deems teaching plumbing to users ("I like it raw!
> So I teach it the same way!") harmful?
There is only one thing that seems to be true about teaching Git (or
anything else) -- there is no single method that works equally well
for anyone. Having said so, I must admit that teaching plumbing will
be probably not a good idea for most users, yet there are some who
prefer bottom-up approach. Some users will prefer to connect Git
functionality to their particular needs and solving some practical
tasks that they do day in, day out, while others may prefer to start
with more abstract things like DAG, structure of data, etc... For
the later users, when you explained these basic things, you do not
have to explain commands at all. They may occasionally ask you
something like: git grep works fine for me when I need to find
something in arbitrary file at some particular revision, but how
about finding something in a particular file at arbitrary revision?
Then you say -- look at git log, it should have the grep option. It
is usually all explanations that you need to provide for them. The
rest, they will quickly pick up on their own. Yet, majority users are
not like that. They seem to prefer to start with specific use cases
and only basic porcelain commands... So, I agree with you here.
Dmitry
^ permalink raw reply
* Re: [PATCH] rebase-i: keep old parents when preserving merges
From: Stephan Beyer @ 2008-07-16 21:51 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Schindelin, git
In-Reply-To: <7vd4ldpl3k.fsf@gitster.siamese.dyndns.org>
Hi,
Junio C Hamano wrote:
> Stephan Beyer <s-beyer@gmx.net> writes:
>
> ... Based on the discussion thread, here is a rewrite of the log message.
>
> > When "rebase -i -p" tries to preserve merges of unrelated branches, it
> > lost some parents:
> >
> > - When you have more than two parents, the commit in the new history
> > ends up with fewer than expected number of parents and this breakage
> > goes unnoticed;
> >
> > - When you are rebasing a merge with two parents and one is lost, the
> > command tries to cherry-pick the original merge commit, and the command
> > fails.
> >
> > Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Ok, big thanks :)
> > diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> > index a35212d..0df7640 100755
> > --- a/git-rebase--interactive.sh
> > +++ b/git-rebase--interactive.sh
> > @@ -174,6 +174,8 @@ pick_one_preserving_merges () {
> > new_parents="$new_parents $new_p"
> > ;;
> > esac
> > + else
> > + new_parents="$new_parents $p"
> > fi
> > done
>
> Reading the surrounding code, it makes me wonder if you also need to futz
> with variables like $preserve and $fast_forward.
No, I would not see a reason for that.
Regards,
Stephan
--
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Daniel Barkalow @ 2008-07-16 21:53 UTC (permalink / raw)
To: Avery Pennarun; +Cc: Johannes Schindelin, git
In-Reply-To: <32541b130807161135h64024151xc60e23d222a3a508@mail.gmail.com>
On Wed, 16 Jul 2008, Avery Pennarun wrote:
> On 7/16/08, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>
> > > At the very least, there will be branches.
> >
> > Oh. And you have to teach plumbing for that?
>
> In svn, a branch is a revision-controlled directory. In git, a branch
> is a "ref". What's a ref? Well, it's a name for a commit. What's a
> commit? Well, it's a blob. What's a blob? Err, that's complicated.
You're simply wrong. A ref isn't a name for a commit (the point of having
a ref is that it doesn't persist in naming the same commit). A commit
isn't a blob. If you start telling people complicated and wrong things,
they're surely going to be confused.
Git maintains history as a directed graph, with each commit pointing back
at its history. Refs are the what holds the newest commits that nothing
else points back to. If directed graphs aren't in your users' experience,
you can put it this way: git maintains history like knitting, where each
new stitch holds on to one or more previous stitches, and refs are the
knitting needles that hold the ends where you're working (except that
knitting is a lot wider than software development). gitk --all even
provides the diagram you want to explain it.
SVN branches are incredible confusing because they fail to distinguish the
directory structure of the project's source tree from the arrangement of
available latest versions. And the version numbers for your branch
increase when changes are made to other branches.
> > I will not even bother to reply to your mentioning rebase, submodules, and
> > the "complicated" log due to merges for that very reason: all of this can
> > be done, easily, with porcelain.
>
> My point was that the porcelain doesn't even make that stuff easy, and
> thus you need to understand fundamental git internal concepts to use
> them, and fundamental git internals are easiest to teach using the
> plumbing, which doesn't try to hide them.
I don't think the plumbing does a particularly good job of elucidating the
fundamental git internals; the plumbing does single operations on the
fundamental structures, but that doesn't explain what the fundamental
structures are, or what they mean, or why you'd do particular things to
them. In fact, they don't at all show the difference between what's
expected to change frequently and what's permanent, which will tend to
give you wrong ideas.
And for understanding the basic objects, "git show" will work better than
"git cat-file" (there's no fundamental reason that trees are binary data
and other types aren't, and no particular reason to care about the time
format in commit headers, etc), and the plumbing programs for creating the
fundamental objects are an even more uneven and arbitrary presentation.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Dmitry Potapov @ 2008-07-16 21:59 UTC (permalink / raw)
To: Avery Pennarun; +Cc: Junio C Hamano, Johannes Schindelin, git
In-Reply-To: <32541b130807161151x19c20f9t91b7fb9b8c7b8c7b@mail.gmail.com>
On Wed, Jul 16, 2008 at 02:51:30PM -0400, Avery Pennarun wrote:
>
> svn avoids these excess merges by default, albeit because it puts your
> working copy at risk every time you do "svn update".
You can do "git pull --rebase" if you like. And there is a configuration
option that allows you to avoid typing --rebase every time. Or did you
mean to being to do that without saving your changes? I think the later
is really a bogus idea, and it should not be encouraged. The worst than
that can be only say "svn update" while you still have not saved changes
in your editor. Then you will have even more fun. So the rule should be:
save your changes first, and only then pull from the upstream.
BTW, one thing is to avoid excessive merges, and the other thing is to
do not have this feature at all. SVN is still not capable to merge,
because merge means to have more than one parent. SVN cannot do that.
What SVN does instead is very limited and buggy cherry-picking:
http://subversion.tigris.org/issues/show_bug.cgi?id=2897
In fact, this is not cherry-picking patches but per-file cherry-picking
and due to limitations of their automatic revision filtering, they have
a nice feature -- to edit svn:mergeinfo manually. Obviously, it is
impossible to visualize this per-file property well. Thus when you are
going to merge something in SVN, you have no slightest idea what you are
really doing.
Have fun,
Dmitry
^ permalink raw reply
* Re: [PATCH] Reformat "your branch has diverged..." lines to reduce line length.
From: Junio C Hamano @ 2008-07-16 22:03 UTC (permalink / raw)
To: Avery Pennarun; +Cc: git
In-Reply-To: <32541b130807161327k17f3a58ay5ab2da75963a2d50@mail.gmail.com>
"Avery Pennarun" <apenwarr@gmail.com> writes:
>> Your branch is ahead of 'origin/add-chickens2' by 21 commits.
>>
>> Your branch is behind 'origin/add-chickens2' by 1 commit.
>>
>> Your branch and 'origin/add-chickens2' have diverged, and have
>> 21 and 1 different commit(s) each, respectively.
>>
>> I moved "respectively" so that the variable parts will come close to the
>> beginning of physical line.
>
> Well, the fact that the number of commits is "variable" isn't so
> important, unless you start diverging by 1e9 commits or something :)
No, no, no. The point is not about keeping it on screen when "less -S"
chops at the right end. The point is to limit eye-movement of the user;
i.e. presenting important information consistently at around the same
column, closer to the left edge. Probably the line break should be before
"and have" to make it even easier to read.
>> Your branch and 'origin/add-chickens2' have diverged,
>> and have 21 and 1 different commit(s) each, respectively.
> Alternatively, your rephrasing above made me think of the idea of just
> printing *both* of the first two messages in the "diverging" case.
I do not think it is such a good idea --- we invite silly comments like
"You say X is ahead of Y, and X is behind of Y, which is true?".
> Please let me know if you want me to resubmit the patch with your
> suggestions or whether you'll handle it. I'm still a little vague on
> the exact patch approval process.
It is very much more "consensus building" than "approval", and at this
point we wait for a day or two to see if people come up with even better
alternatives. Just be kind enough to prod me if I forget after a few
days, though ;-)
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Stephan Beyer @ 2008-07-16 22:09 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <alpine.DEB.1.00.0807161804400.8950@racer>
Hi,
Johannes Schindelin wrote:
[...]
>
> I had the pleasure of introducing Git to a few users in the last months
> and in my opinion, restricting myself to teaching them these commands
> first helped tremendously:
>
> - clone, pull, status, add, commit, push, log
>
> All of these were presented without options, to keep things simple.
Basically I agree, but depending on the user's foreign SCM knowledge
it could be useful to talk about some basic "low-level" concepts of git
(without talking about the plumbing).
I mean:
- objects (commits, trees, blobs ... in very short)
- index
and perhaps
- refs (at least branches)
I was told that before I've seen a first git command and I still think
that was very useful.
Hmm, just recalling, my first git commands were:
1. init
2. add
3. status
4. commit
5. diff
6. log
7. branch
8. checkout
in this order, approximately. :)
(And I've used rebase before merge and I haven't used clone/pull/push for
a long time.)
It seems I haven't touched any plumbing before I've started with GSoC :)
I also think that for a user it is totally irrelevant if it is plumbing or
porcelain she is using, as long as it works. I mean, if I tought someone
using git, I'd never use the words "porcelain" or "plumbing".
Regards,
Stephan
--
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F
^ permalink raw reply
* git-svn: Trouble after project has moved in svn
From: Jukka Zitting @ 2008-07-16 22:12 UTC (permalink / raw)
To: git
Hi,
Somewhat related to the recent thread about Apache Synapse, I'm having
trouble making a git-svn clone of a project that has been moved around
in a Subversion repository.
See the script at the end of this message for a simple test case that
does the following svn commits:
PREPARE: creates projectA with the standard trunk,branches,tags structure
VERSION1: first version of README.txt in projectA/trunk
TAG1: tags projectA/trunk to projectA/tags/v1
MOVE: moves projectA to projectB
VERSION2: second version of README.txt in projectB/trunk
TAG2: tags projectB/trunk to projectB/tags/v2
The resulting repository structure is:
/projectB/
trunk/
README.txt # version 2
branches/
tags/
v1/
README.txt # version 1
v2/
README.txt # version 2
Here's the git commit graph created by the test case:
* TAG2 <- refs/remotes/tags/v2
| * VERSION2 <- refs/remotes/trunk
|/
* MOVE
* VERSION1 <- refs/remotes/trunk@3
| * MOVE <- refs/remotes/tags/v1
| * TAG1 <- refs/remotes/tags/v1@3
|/
* PREPARE <- refs/remotes/tags/v1@1
The most pressing issue is that the refs/remotes/tags/v1 branch starts
directly from the first PREPARE commit instead of VERSION1. Also, the
branch point of refs/remotes/tags/v2 seems to be incorrect, it should
be based on the VERSION2 commit instead of MOVE.
A more accurate commit graph would be:
* TAG2 <- refs/remotes/tags/v2
* VERSION2 <- refs/remotes/trunk
* MOVE
| * MOVE <- refs/remotes/tags/v1
| * TAG1
|/
* VERSION1
* PREPARE
Or even (but I guess git-svn needs to map each svn commit to at least
one git commit, so this probably wouldn't work):
* VERSION2 <- refs/remotes/trunk, refs/remotes/tags/v2
* VERSION1 <- refs/remotes/tags/v1
* PREPARE
I tried working my way through git-svn.perl to figure out how to
improve the way git-svn tracks svn moves, but so far I couldn't figure
out how to do that. Any ideas or hints?
BR,
Jukka Zitting
=====
#!/bin/sh
REPO=`pwd`/repo
svnadmin create $REPO
svn checkout file://$REPO checkout
cd checkout
svn mkdir projectA
svn mkdir projectA/trunk
svn mkdir projectA/branches
svn mkdir projectA/tags
svn commit -m PREPARE
echo VERSION1 > projectA/trunk/README.txt
svn add projectA/trunk/README.txt
svn commit -m VERSION1
svn copy projectA/trunk projectA/tags/v1
svn commit -m TAG1
svn update
svn move projectA projectB
svn commit -m MOVE
echo VERSION2 > projectB/trunk/README.txt
svn commit -m VERSION2
svn copy projectB/trunk projectB/tags/v2
svn commit -m TAG2
svn update
mkdir ../git
cd ../git
git svn init -s file://$REPO/projectB
git svn fetch
^ permalink raw reply
* gitk: Author/Committer name with special characters
From: Torsten Paul @ 2008-07-16 22:24 UTC (permalink / raw)
To: git; +Cc: Paul Mackerras
Hi!
I'm tracking a subversion repository which is running on
a windows machine with git-svn. The user names look like
DOMAIN\username and that's giving a strange display in
gitk as the backslash sequence is evaluated.
I'm not sure if I found the correct place to prevent this,
so I'd like to ask if the following change would be the
correct thing to prepare as patch...
ciao,
Torsten.
diff --git a/gitk-git/gitk b/gitk-git/gitk
index fddcb45..f114fa2 100644
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -1510,10 +1510,10 @@ proc parsecommit {id contents listed} {
set tag [lindex $line 0]
if {$tag == "author"} {
set audate [lindex $line end-1]
- set auname [lrange $line 1 end-2]
+ set auname [join [lrange [split $line] 1 end-2]]
} elseif {$tag == "committer"} {
set comdate [lindex $line end-1]
- set comname [lrange $line 1 end-2]
+ set comname [join [lrange [split $line] 1 end-2]]
}
}
set headline {}
^ permalink raw reply related
* Re: Considering teaching plumbing to users harmful
From: Dmitry Potapov @ 2008-07-16 22:24 UTC (permalink / raw)
To: Avery Pennarun; +Cc: Junio C Hamano, Johannes Schindelin, git
In-Reply-To: <32541b130807161229ob4c21cbsc6c86ee3e42c4101@mail.gmail.com>
On Wed, Jul 16, 2008 at 03:29:39PM -0400, Avery Pennarun wrote:
>
> I find it interesting how git usability discussions tend to go. It
> usually starts out by someone saying, "Look, git really isn't that
> hard to learn, just do it like this..." and then someone says, "But
> actually, that's still really complicated. Everyone thinks xxx other
> VCS is easier to learn. Here's how they do it..."
Everyone thinks so? Somehow, I don't, and there are people who think
that Git is easily to learn if you teach it properly.
> And then someone
> says, "Yeah, but xxx VCS sucks!" and that somehow makes it okay that
> git is empirically harder to learn than xxx VCS, as anyone can see by
> browsing the web.
Browsing the web is not an empirical study. And if you say harder, you
should specify to whom. To those who already know xxx VCS, naturally
anything new or different than what you got used to will be difficult
at the beginning. Naturally, it is easier to learn something if there
are more books and articles about it, or just there are more people who
can answer on any your questions. But with everything else being equal,
do you really believe that SVN or CVS is easier to use than Git if we
speak about learning comparable functionality? What is your argument
for that? "svn update"? Well, it is a sure way to make mess in your
working directoy. So, your argument does not sound very convincing.
Dmitry
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Johannes Schindelin @ 2008-07-16 22:28 UTC (permalink / raw)
To: Avery Pennarun; +Cc: Junio C Hamano, git
In-Reply-To: <32541b130807161229ob4c21cbsc6c86ee3e42c4101@mail.gmail.com>
Hi,
On Wed, 16 Jul 2008, Avery Pennarun wrote:
> I find it interesting how git usability discussions tend to go.
I find it not interesting at all, even slightly annoying, that I cannot
seem to start a perfectly valid discussion about advocating porcelain, and
trying to even avoid mentioning plumbing in user-visible documentation,
without somebody highjacking the thread to talk about svn.
I am disinterested in svn. So disinterested that I do not even want to
read about it. What we could learn from svn, we did, positive and
negative lessons, now there is nothing more to be seen here, please move
along.
So can those people who have something to say about _my_ subject of
discussion please speak up? I think this issue has not been discussed
properly.
Thanks.
Dscho
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Theodore Tso @ 2008-07-16 22:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Avery Pennarun, Johannes Schindelin, git
In-Reply-To: <7vr69tpoze.fsf@gitster.siamese.dyndns.org>
On Wed, Jul 16, 2008 at 01:12:53PM -0700, Junio C Hamano wrote:
> If you are advocating that mode of operation to be easy in git, you should
> think again. That pull (be it with or without --rebase) can conflict and
> you would need to resolve it, and then your "stash pop" can conflict
> again. You can have your own "git avery-up" alias which is your "svn up"
> equivalent, but if you train users with that first, the users have to
> learn how to cope with conflicts in individual steps anyway.
>
> Making these three into a single alias is not an improvement either. If
> you are not ready to incorporate other's changes to your history, why are
> you pulling? Being distributed gives the power of working independently
> and at your own pace. You should train your brain to think about the
> workflow first. "You should stash before pull" is _not_ a good advice.
> "Do not pull when you are not ready" is.
What I've found is that some people will take that advice, and other
people won't. Saying that you are thinking about things the wrong way
doesn't really help for people who have been so ingrained into an old
way of doing things. Indeed, it can end up sounding very elistist.
So from a pedagogical perspective, what I would probably do is show
them how to replicate svn-up, and explain to them how this script
works:
#!/bin/sh
# git-up
if git diff --quiet && git diff --quiet --cached ; then
git pull $*
else
git stash ; git pull $*; git stash pop
fi
And then tell them that if this put this into their path, then "git
up" will work the same way as "svn up" --- but that git has a better
way of doing things, and why it is so. And then what I would tell
them is that no really, merges are really easy with git, and that even
if they were to rely on the "git up" alias as a crutch, that over time
they would find that there are much more natural, easy, and powerful
ways of doing things.
In general, I find that people are more willing to listen to "we have
a more powerful way of doing things", if you can first give them the
equivalent of the "dumb and stupid" way that they are used to doing
things so they can switch to the new tool right away without too much
of a steep learning curve; they will then switch to the more
advanced/powerful workflows at their own pace. Other people may have
other pedgogical techniques, but I find mine to work fairly well.
Regards,
- Ted
^ permalink raw reply
* Re: [PATCH 6/7] git rm: Support for removing submodules
From: Johannes Schindelin @ 2008-07-16 22:41 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
In-Reply-To: <20080716191134.19772.85003.stgit@localhost>
Hi,
On Wed, 16 Jul 2008, Petr Baudis wrote:
> This patch adds support for removing submodules to 'git rm', including
> removing the appropriate sections from the .gitmodules file to reflect
> this
I have no time to look at the whole series, or even at the patch, but I
have concerns. Do you really remove the whole directory? Because if you
do, you remove more than what can be possibly reconstructed from the
object store.
That is much more dangerous than what "git rm" does.
For example, you can have local branches, remote settings, untracked
files, etc. in the subdirectory. And that cannot be recovered once
deleted.
I wonder if it really makes sense to integrate that into git-rm, and not
git-submodule, if only to introduce another level of consideration for the
user before committing what is potentially a big mistake.
Ciao,
Dscho
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Junio C Hamano @ 2008-07-16 22:41 UTC (permalink / raw)
To: Theodore Tso; +Cc: Avery Pennarun, Johannes Schindelin, git
In-Reply-To: <20080716223205.GK2167@mit.edu>
Theodore Tso <tytso@mit.edu> writes:
> So from a pedagogical perspective, what I would probably do is show
> them how to replicate svn-up, and explain to them how this script
> works:
>
> #!/bin/sh
> # git-up
>
> if git diff --quiet && git diff --quiet --cached ; then
> git pull $*
> else
> git stash ; git pull $*; git stash pop
> fi
Looks good, except:
if git diff ....; then
git pull "$@"
else
git stash && git pull "$@" && git stash pop
fi
to make sure the conflict notices won't be scrolled off by error messages
from the later commands.
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Theodore Tso @ 2008-07-16 22:49 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Avery Pennarun, Junio C Hamano, git
In-Reply-To: <alpine.DEB.1.00.0807170024310.4318@eeepc-johanness>
On Thu, Jul 17, 2008 at 12:28:27AM +0200, Johannes Schindelin wrote:
> Hi,
>
> On Wed, 16 Jul 2008, Avery Pennarun wrote:
>
> > I find it interesting how git usability discussions tend to go.
>
> I find it not interesting at all, even slightly annoying, that I cannot
> seem to start a perfectly valid discussion about advocating porcelain, and
> trying to even avoid mentioning plumbing in user-visible documentation,
> without somebody highjacking the thread to talk about svn.
I've already said I agree with you, but maybe it would be helpful if
you focused the discussion a little more with a concrete suggestion
about how we could improve the user-visible documentation. For
example, it is already the case that "git help" only shows porcelain
commands, that has been a big step forward.
So a concrete suggestion might be to move the list of plumbing
commands from the top-level git man page to a "git-plumbing" man page.
I'll note that the git user manual is pretty good about avoiding the
use of git plumbing commands. It's not until Chapter 9, "Low Level
Git Commands" that it start going into the plumbing. (There are a
couple of mentions of git rev-parse before chapter 9, but that's about
it that I could find).
Was there other git documentation where you think there is too many
references to git plumbing?
- Ted
^ permalink raw reply
* Re: Considering teaching plumbing to users harmful
From: Sean Kelley @ 2008-07-16 22:53 UTC (permalink / raw)
To: git
In-Reply-To: <20080716223205.GK2167@mit.edu>
Hi
On Wed, Jul 16, 2008 at 5:32 PM, Theodore Tso <tytso@mit.edu> wrote:
>
> In general, I find that people are more willing to listen to "we have
> a more powerful way of doing things", if you can first give them the
> equivalent of the "dumb and stupid" way that they are used to doing
> things so they can switch to the new tool right away without too much
> of a steep learning curve; they will then switch to the more
> advanced/powerful workflows at their own pace. Other people may have
> other pedgogical techniques, but I find mine to work fairly well.
>
> Regards,
>
> - Ted
When one has 100 users in a company using a DVCS, you really need some
sort of simplified workflow documented and taught. Not everyone who
writes code is particularly keen on the vagaries of a VCS' commands.
I know that must be shocking to this audience the GIT list, but it is
very very true. They don't give a crap what sort of weird command
combination one can pull out of the 100 or so commands when you type
git-<tab> at a bash prompt. They just want the damn thing to behave
in a somewhat friendly fashion. They want to check in their code and
get on with software development and not over analyzing how many ways
they can do the same command. In my experience, what Ted is
suggesting is the only way to handle it. Most developers just want it
to work and focus on debugging their project. Never expect your users
to have the same interest as you in VCS.
Sean
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox