Merge branch 'jk/pull-into-dirty-unborn'
authorJunio C Hamano <gitster@pobox.com>
Thu, 27 Jun 2013 21:29:52 +0000 (14:29 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 27 Jun 2013 21:29:52 +0000 (14:29 -0700)
"git pull" into nothing trashed "local changes" that were in the
index, and this avoids it.

* jk/pull-into-dirty-unborn:
pull: merge into unborn by fast-forwarding from empty tree
pull: update unborn branch tip after index

1  2 
git-pull.sh
t/t5520-pull.sh
diff --combined git-pull.sh
index 638aabb7b347e2afeb9bf327902de9e3702cd9d4,2c502171f7fb7bc6e13c65dfd72e920e8b021a3b..6828e2c7157fd80905e864b475c11ccc7a330e03
@@@ -39,7 -39,7 +39,7 @@@ test -z "$(git ls-files -u)" || die_con
  test -f "$GIT_DIR/MERGE_HEAD" && die_merge
  
  strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
 -log_arg= verbosity= progress= recurse_submodules=
 +log_arg= verbosity= progress= recurse_submodules= verify_signatures=
  merge_args= edit=
  curr_branch=$(git symbolic-ref -q HEAD)
  curr_branch_short="${curr_branch#refs/heads/}"
        --no-recurse-submodules)
                recurse_submodules=--no-recurse-submodules
                ;;
 +      --verify-signatures)
 +              verify_signatures=--verify-signatures
 +              ;;
 +      --no-verify-signatures)
 +              verify_signatures=--no-verify-signatures
 +              ;;
        --d|--dr|--dry|--dry-|--dry-r|--dry-ru|--dry-run)
                dry_run=--dry-run
                ;;
@@@ -266,10 -260,17 +266,17 @@@ case "$merge_head" i
        ;;
  esac
  
+ # Pulling into unborn branch: a shorthand for branching off
+ # FETCH_HEAD, for lazy typers.
  if test -z "$orig_head"
  then
-       git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
-       git read-tree -m -u HEAD || exit 1
+       # Two-way merge: we claim the index is based on an empty tree,
+       # and try to fast-forward to HEAD.  This ensures we will not
+       # lose index/worktree changes that the user already made on
+       # the unborn branch.
+       empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+       git read-tree -m -u $empty_tree $merge_head &&
+       git update-ref -m "initial pull" HEAD $merge_head "$curr_head"
        exit
  fi
  
@@@ -289,7 -290,7 +296,7 @@@ true
        eval="$eval --onto $merge_head ${oldremoteref:-$merge_head}"
        ;;
  *)
 -      eval="git-merge $diffstat $no_commit $edit $squash $no_ff $ff_only"
 +      eval="git-merge $diffstat $no_commit $verify_signatures $edit $squash $no_ff $ff_only"
        eval="$eval  $log_arg $strategy_args $merge_args $verbosity $progress"
        eval="$eval \"\$merge_name\" HEAD $merge_head"
        ;;
diff --combined t/t5520-pull.sh
index 6af6c63350383e049082e61d3c8133af79d5a749,dd24b0cdbbdda50997ec0cacdf569cae7fa2c613..ed4d9c83181bc45456074f053ed5a0f137fc7e27
@@@ -57,6 -57,35 +57,35 @@@ test_expect_success 'pulling into void 
        )
  '
  
+ test_expect_success 'pulling into void does not overwrite staged files' '
+       git init cloned-staged-colliding &&
+       (
+               cd cloned-staged-colliding &&
+               echo "alternate content" >file &&
+               git add file &&
+               test_must_fail git pull .. master &&
+               echo "alternate content" >expect &&
+               test_cmp expect file &&
+               git cat-file blob :file >file.index &&
+               test_cmp expect file.index
+       )
+ '
+ test_expect_success 'pulling into void does not remove new staged files' '
+       git init cloned-staged-new &&
+       (
+               cd cloned-staged-new &&
+               echo "new tracked file" >newfile &&
+               git add newfile &&
+               git pull .. master &&
+               echo "new tracked file" >expect &&
+               test_cmp expect newfile &&
+               git cat-file blob :newfile >newfile.index &&
+               test_cmp expect newfile.index
+       )
+ '
  test_expect_success 'test . as a remote' '
  
        git branch copy master &&
@@@ -96,7 -125,8 +125,7 @@@ test_expect_success '--rebase' 
  '
  test_expect_success 'pull.rebase' '
        git reset --hard before-rebase &&
 -      git config --bool pull.rebase true &&
 -      test_when_finished "git config --unset pull.rebase" &&
 +      test_config pull.rebase true &&
        git pull . copy &&
        test $(git rev-parse HEAD^) = $(git rev-parse copy) &&
        test new = $(git show HEAD:file2)
  
  test_expect_success 'branch.to-rebase.rebase' '
        git reset --hard before-rebase &&
 -      git config --bool branch.to-rebase.rebase true &&
 -      test_when_finished "git config --unset branch.to-rebase.rebase" &&
 +      test_config branch.to-rebase.rebase true &&
        git pull . copy &&
        test $(git rev-parse HEAD^) = $(git rev-parse copy) &&
        test new = $(git show HEAD:file2)
  
  test_expect_success 'branch.to-rebase.rebase should override pull.rebase' '
        git reset --hard before-rebase &&
 -      git config --bool pull.rebase true &&
 -      test_when_finished "git config --unset pull.rebase" &&
 -      git config --bool branch.to-rebase.rebase false &&
 -      test_when_finished "git config --unset branch.to-rebase.rebase" &&
 +      test_config pull.rebase true &&
 +      test_config branch.to-rebase.rebase false &&
        git pull . copy &&
        test $(git rev-parse HEAD^) != $(git rev-parse copy) &&
        test new = $(git show HEAD:file2)
@@@ -167,9 -200,9 +196,9 @@@ test_expect_success 'pull --rebase die
        git update-ref refs/remotes/me/copy copy^ &&
        COPY=$(git rev-parse --verify me/copy) &&
        git rebase --onto $COPY copy &&
 -      git config branch.to-rebase.remote me &&
 -      git config branch.to-rebase.merge refs/heads/copy &&
 -      git config branch.to-rebase.rebase true &&
 +      test_config branch.to-rebase.remote me &&
 +      test_config branch.to-rebase.merge refs/heads/copy &&
 +      test_config branch.to-rebase.rebase true &&
        echo dirty >> file &&
        git add file &&
        test_must_fail git pull &&