Download raw body.
Got publishes local unversioned bytes during merge and rebase
Got publishes local unversioned bytes during merge and rebase
Got publishes local unversioned bytes during merge and rebase
Thanks for the update. I replayed the candidate fix against Got 0.128 for
regular-file, ignored-file, unversioned-directory, and symlink-to-directory
collisions. In each merge case, Got reports the obstruction, leaves
`refs/heads/main` unchanged, and does not add the incoming path to the
merge tree.
I also tested rebase and histedit with directory and symlink obstructions.
Both operations stop with the work tree in the expected interrupted state
and do not advance or publish the obstructed path. The `lstat()` change
together with the `upa.obstructed` guards addresses the residual cases I
reported, so the patch looks complete for this issue.
On Sun, Sep 20, 2026 at 7:22 PM Stefan Sperling <stsp@stsp.name> wrote:
> On Sun, Sep 20, 2026 at 11:17:01AM +0800, Yann Lorwyn wrote:
> > Thank you for acknowledging the issue and for preparing the proposed test
> > and
> > fix. I replayed it against Got 0.128. It blocks the regular-file and
> ignored
> > regular-file cases, but I found two residual cases:
> >
> > - With the patch as written, a local symlink to a directory is followed
> by
> > `stat()`, reported as obstructed, and `got merge` still advances
> > `refs/heads/main` while omitting the incoming path from the merge tree.
> > - A local unversioned directory produces the same result.
> >
> > Changing `stat()` to `lstat()` blocks the symlink case, but the directory
> > case
> > remains because merge, rebase, and histedit do not treat `upa.obstructed`
> > as a
> > stop condition. I suggest using `lstat()` and adding `upa.obstructed >
> 0` to
> > those postpone guards. I also recommend regression tests for symlink-to-
> > directory and directory collisions that assert that the target ref does
> not
> > move and that the incoming tree entry is not silently omitted.
>
> Right. Our work tree code should always be using lstat() since we need
> to always consider the symlink case.
>
> > So I believe the original issue is addressed for regular files, but the
> > current patch still has a history-integrity residual for obstructing
> > directories and symlinks. I have recorded the replay details and exact
> > outcomes, and I can provide a shorter regression-test-oriented patch if
> that
> > would be useful.
>
> I agree that obstructions should interrupt the merge to allow users to
> double-check the merge result.
>
> I have added more tests which should cover all cases. And I have updated
> our documentation to mention the term "obstruction" since users should
> be aware of this term.
>
> The problem does not affect 'got merge' only. The 'got histedit' and
> 'got rebsae' commands use a similar mechanism to interrupt the operation
> if a problem is found. These two commands were also blind to obstructions,
> which I am fixing below. I am not adding separate test cases for these
> commands right now. It would be good to test them, too, but we'd be mostly
> adding test coverage for trivial code in got.c, since the shared worktree.c
> code path is already covered via 'got merge'.
>
> Other commands have to deal with obstructions are 'got update' and commands
> which inherit behaviour from 'got update', such as 'got branch' and
> 'got integrate'. I have added a new test which covers 'got integrate' to
> our Git repository's main branch, which shows that the repository state
> is OK after integrating a branch with an obstruction in the work tree.
> The obstruction only persists in the work tree which triggered the
> integration
> merge. This is a fast-forward merge in Git terms, so there is no risk of
> exposing files which haven't already been committed.
>
> Does this patch look complete to you?
>
>
> M got/got.1 | 12+ 9-
> M got/got.c | 7+ 5-
> M lib/worktree.c | 15+ 0-
> M regress/cmdline/histedit.sh | 17+ 6-
> M regress/cmdline/merge.sh | 365+ 0-
>
> 5 files changed, 416 insertions(+), 20 deletions(-)
>
> commit - 9a4a6d862f3654b1d1d114f098cf7c487ea71660
> commit + 81c98775c04265beb18bc4203bca6a627ddfcfac
> blob - 63826d61eff2e1b84f540049b83bc496e59594cb
> blob + 30e95121f9931e85ac3aa874bffa1a6d9525a861
> --- got/got.1
> +++ got/got.1
> @@ -2621,7 +2621,7 @@ Show the status of each affected file, using the
> follo
> .It D Ta file was deleted
> .It d Ta file's deletion was prevented by local modifications
> .It A Ta new file was added
> -.It \(a~ Ta changes destined for a non-regular file were not merged
> +.It \(a~ Ta changes obstructed by a non-regular file were not merged
> .It ? Ta changes destined for an unversioned file were not merged
> .El
> .Pp
> @@ -2764,7 +2764,7 @@ Show the status of each affected file, using the
> follo
> .It D Ta file was deleted
> .It d Ta file's deletion was prevented by local modifications
> .It A Ta new file was added
> -.It \(a~ Ta changes destined for a non-regular file were not merged
> +.It \(a~ Ta changes obstructed by a non-regular file were not merged
> .It ? Ta changes destined for an unversioned file were not merged
> .El
> .Pp
> @@ -2927,13 +2927,14 @@ using the following status codes:
> .It D Ta file was deleted
> .It d Ta file's deletion was prevented by local modifications
> .It A Ta new file was added
> -.It \(a~ Ta changes destined for a non-regular file were not merged
> +.It \(a~ Ta changes obstructed by a non-regular file were not merged
> .It ? Ta changes destined for an unversioned file were not merged
> .El
> .Pp
> If merge conflicts occur, the rebase operation is interrupted and may
> be continued once conflicts have been resolved.
> -If any files with destined changes are found to be missing or unversioned,
> +If any files with destined changes are found to be missing, unversioned,
> +or obstructed,
> or if files could not be deleted due to differences in deleted content,
> the rebase operation will be interrupted to prevent potentially incomplete
> changes from being committed to the repository without user intervention.
> @@ -3196,13 +3197,14 @@ using the following status codes:
> .It D Ta file was deleted
> .It d Ta file's deletion was prevented by local modifications
> .It A Ta new file was added
> -.It \(a~ Ta changes destined for a non-regular file were not merged
> +.It \(a~ Ta changes obstructed by a non-regular file were not merged
> .It ? Ta changes destined for an unversioned file were not merged
> .El
> .Pp
> If merge conflicts occur, the histedit operation is interrupted and may
> be continued once conflicts have been resolved.
> -If any files with destined changes are found to be missing or unversioned,
> +If any files with destined changes are found to be missing, unversioned,
> +or obstructed,
> or if files could not be deleted due to differences in deleted content,
> the histedit operation will be interrupted to prevent potentially
> incomplete
> changes from being committed to the repository without user intervention.
> @@ -3497,13 +3499,14 @@ using the following status codes:
> .It D Ta file was deleted
> .It d Ta file's deletion was prevented by local modifications
> .It A Ta new file was added
> -.It \(a~ Ta changes destined for a non-regular file were not merged
> +.It \(a~ Ta changes obstructed by a non-regular file were not merged
> .It ? Ta changes destined for an unversioned file were not merged
> .El
> .Pp
> If merge conflicts occur, the merge operation is interrupted and conflicts
> must be resolved before the merge operation can continue.
> -If any files with destined changes are found to be missing or unversioned,
> +If any files with destined changes are found to be missing, unversioned,
> +or obstructed,
> or if files could not be deleted due to differences in deleted content,
> the merge operation will be interrupted to prevent potentially incomplete
> changes from being committed to the repository without user intervention.
> @@ -3726,7 +3729,7 @@ Show the status of each affected file, using the
> follo
> .It ! Ta changes destined for a missing file were not merged
> .It D Ta file was staged as deleted and still is deleted
> .It d Ta file's deletion was prevented by local modifications
> -.It \(a~ Ta changes destined for a non-regular file were not merged
> +.It \(a~ Ta changes obstructed by a non-regular file were not merged
> .El
> .Pp
> The options for
> blob - 38f8789c90e1c72d22ff3a64eae928bd982965d5
> blob + 590d82ff913f113811ff2c911339e3bd2ccd76a7
> --- got/got.c
> +++ got/got.c
> @@ -12051,7 +12051,8 @@ cmd_rebase(int argc, char *argv[])
>
> print_merge_progress_stats(&upa);
> if (upa.conflicts > 0 || upa.missing > 0 ||
> - upa.not_deleted > 0 || upa.unversioned > 0) {
> + upa.not_deleted > 0 || upa.unversioned > 0 ||
> + upa.obstructed > 0) {
> if (upa.conflicts > 0) {
> error =
> show_rebase_merge_conflict(&qid->id,
> repo);
> @@ -12070,7 +12071,7 @@ cmd_rebase(int argc, char *argv[])
> }
>
> if (upa.conflicts > 0 || upa.missing > 0 ||
> - upa.not_deleted > 0 || upa.unversioned > 0) {
> + upa.not_deleted > 0 || upa.unversioned > 0 || upa.obstructed >
> 0) {
> error = got_worktree_rebase_postpone(worktree, fileindex);
> if (error)
> goto done;
> @@ -13476,7 +13477,8 @@ cmd_histedit(int argc, char *argv[])
>
> print_merge_progress_stats(&upa);
> if (upa.conflicts > 0 || upa.missing > 0 ||
> - upa.not_deleted > 0 || upa.unversioned > 0) {
> + upa.not_deleted > 0 || upa.unversioned > 0 ||
> + upa.obstructed > 0) {
> if (upa.conflicts > 0) {
> error = show_rebase_merge_conflict(
> hle->commit_id, repo);
> @@ -13518,7 +13520,7 @@ cmd_histedit(int argc, char *argv[])
> }
>
> if (upa.conflicts > 0 || upa.missing > 0 ||
> - upa.not_deleted > 0 || upa.unversioned > 0) {
> + upa.not_deleted > 0 || upa.unversioned > 0 || upa.obstructed >
> 0) {
> error = got_worktree_histedit_postpone(worktree,
> fileindex);
> if (error)
> goto done;
> @@ -14031,7 +14033,7 @@ cmd_merge(int argc, char *argv[])
> goto done;
> printf("Merge of %s interrupted on request\n",
> branch_name);
> } else if (upa.conflicts > 0 || upa.missing > 0 ||
> - upa.not_deleted > 0 || upa.unversioned > 0) {
> + upa.not_deleted > 0 || upa.unversioned > 0 || upa.obstructed >
> 0) {
> error = got_worktree_merge_postpone(worktree, fileindex);
> if (error)
> goto done;
> blob - b3c50d7a852f627a1de9da592bcf0d73dcdd5ac4
> blob + ce14148aeec6703b28ab237718530ce6b8debca7
> --- lib/worktree.c
> +++ lib/worktree.c
> @@ -3345,6 +3345,21 @@ merge_file_cb(void *arg, struct got_blob_object
> *blob1
> goto done;
> }
> } else {
> + if (lstat(ondisk_path, &sb) == -1) {
> + if (errno != ENOENT && errno != ENOTDIR) {
> + err = got_error_from_errno2("stat",
> + ondisk_path);
> + goto done;
> + }
> + } else {
> + if (S_ISREG(sb.st_mode) ||
> S_ISLNK(sb.st_mode))
> + status = GOT_STATUS_UNVERSIONED;
> + else
> + status = GOT_STATUS_OBSTRUCTED;
> + err = (*a->progress_cb)(a->progress_arg,
> + status, path2);
> + goto done;
> + }
> err = add_file(a->worktree, a->fileindex, NULL,
> ondisk_path, path2, blob2, mode2,
> 0, 0, 1, a->allow_bad_symlinks,
> blob - 1d993e2f9340895b63648eeed66a23d0497eaa8a
> blob + c936996937241a7920b5ca639a7275d88af88a1c
> --- regress/cmdline/histedit.sh
> +++ regress/cmdline/histedit.sh
> @@ -3030,17 +3030,17 @@ test_histedit_added_file() {
> # +2f81c7988242 -> no-op change: add new file
> echo new > $testroot/wt/new
>
> - (cd $testroot/wt && got histedit -f > $testroot/stdout)
> + (cd $testroot/wt && got histedit -f > $testroot/stdout \
> + 2> $testroot/stderr)
> local new_commit=`git_show_head $testroot/repo`
>
> local short_commit2=`trim_obj_id 12 $commit2`
> local short_new_commit=`trim_obj_id 12 $new_commit`
>
> - echo "A new" > $testroot/stdout.expected
> - echo "$short_commit2 -> $short_new_commit: add new file" \
> - >> $testroot/stdout.expected
> - echo "Switching work tree to refs/heads/master" \
> - >> $testroot/stdout.expected
> + cat > $testroot/stdout.expected <<EOF
> +? new
> +Files not merged because an unversioned file was found in the work tree: 1
> +EOF
>
> cmp -s $testroot/stdout.expected $testroot/stdout
> ret=$?
> @@ -3050,6 +3050,17 @@ test_histedit_added_file() {
> return 1
> fi
>
> + cat > $testroot/stderr.expected <<EOF
> +got: changes destined for some files were not yet merged and should be
> merged manually if required before the histedit operation is continued
> +EOF
> + cmp -s $testroot/stderr.expected $testroot/stderr
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stderr.expected $testroot/stderr
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> test_done "$testroot" "$ret"
> }
>
> blob - 576400c021a6d57ecea5c86d8e2478d39b7be3b9
> blob + 24217948b63b93f44d3919fe19ef8ca82e01b72d
> --- regress/cmdline/merge.sh
> +++ regress/cmdline/merge.sh
> @@ -2331,6 +2331,367 @@ EOF
> test_done "$testroot" "$ret"
> }
>
> +test_merge_adds_ignored_file() {
> + local testroot=`test_init merge_adds_ignored_file`
> + local commit0=`git_show_head $testroot/repo`
> + local commit0_author_time=`git_show_author_time $testroot/repo`
> +
> + git -C $testroot/repo checkout -q -b newbranch
> + echo "new file on branch" > $testroot/repo/gamma/new
> + git -C $testroot/repo add gamma/new > /dev/null
> + git_commit $testroot/repo -m "committing to new file on newbranch"
> + local branch_commit=`git_show_branch_head $testroot/repo newbranch`
> +
> + git -C $testroot/repo checkout -q master
> + echo gamma/new > $testroot/repo/.gitignore
> + git -C $testroot/repo add .gitignore > /dev/null
> + echo "ignoring new file on master branch" >
> $testroot/repo/epsilon/zeta
> + git_commit $testroot/repo -m "committing to zeta on master"
> + local master_commit=`git_show_head $testroot/repo`
> +
> + got checkout -b master $testroot/repo $testroot/wt > /dev/null
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + echo "got checkout failed unexpectedly" >&2
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + echo 'this file is being ignored' > $testroot/wt/gamma/new
> +
> + (cd $testroot/wt && got status > $testroot/stdout)
> +
> + echo -n > $testroot/stdout.expected
> +
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + (cd $testroot/wt && got status -I > $testroot/stdout)
> +
> + cat > $testroot/stdout.expected <<EOF
> +? gamma/new
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cat > $testroot/stderr.expected <<EOF
> +got: changes destined for some files were not yet merged and should be
> merged manually if required before the merge operation is continued
> +EOF
> + (cd $testroot/wt && got merge newbranch \
> + > $testroot/stdout 2> $testroot/stderr)
> + ret=$?
> + if [ $ret -eq 0 ]; then
> + echo "got merge succeeded unexpectedly" >&2
> + test_done "$testroot" "1"
> + return 1
> + fi
> +
> + local merge_commit=`git_show_head $testroot/repo`
> +
> + cat > $testroot/stdout.expected <<EOF
> +? gamma/new
> +Files not merged because an unversioned file was found in the work tree: 1
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cmp -s $testroot/stderr.expected $testroot/stderr
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stderr.expected $testroot/stderr
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + test_done "$testroot" "$ret"
> +}
> +
> +test_merge_adds_ignored_symlink() {
> + local testroot=`test_init merge_adds_ignored_symlink`
> + local commit0=`git_show_head $testroot/repo`
> + local commit0_author_time=`git_show_author_time $testroot/repo`
> +
> + git -C $testroot/repo checkout -q -b newbranch
> + echo "new file on branch" > $testroot/repo/gamma/new
> + git -C $testroot/repo add gamma/new > /dev/null
> + git_commit $testroot/repo -m "committing to new file on newbranch"
> + local branch_commit=`git_show_branch_head $testroot/repo newbranch`
> +
> + git -C $testroot/repo checkout -q master
> + echo gamma/new > $testroot/repo/.gitignore
> + git -C $testroot/repo add .gitignore > /dev/null
> + echo "ignoring new file on master branch" >
> $testroot/repo/epsilon/zeta
> + git_commit $testroot/repo -m "committing to zeta on master"
> + local master_commit=`git_show_head $testroot/repo`
> +
> + got checkout -b master $testroot/repo $testroot/wt > /dev/null
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + echo "got checkout failed unexpectedly" >&2
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + ln -s ../alpha $testroot/wt/gamma/new
> +
> + (cd $testroot/wt && got status > $testroot/stdout)
> +
> + echo -n > $testroot/stdout.expected
> +
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + (cd $testroot/wt && got status -I > $testroot/stdout)
> +
> + cat > $testroot/stdout.expected <<EOF
> +? gamma/new
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cat > $testroot/stderr.expected <<EOF
> +got: changes destined for some files were not yet merged and should be
> merged manually if required before the merge operation is continued
> +EOF
> + (cd $testroot/wt && got merge newbranch \
> + > $testroot/stdout 2> $testroot/stderr)
> + ret=$?
> + if [ $ret -eq 0 ]; then
> + echo "got merge succeeded unexpectedly" >&2
> + test_done "$testroot" "1"
> + return 1
> + fi
> +
> + local merge_commit=`git_show_head $testroot/repo`
> +
> + cat > $testroot/stdout.expected <<EOF
> +? gamma/new
> +Files not merged because an unversioned file was found in the work tree: 1
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cmp -s $testroot/stderr.expected $testroot/stderr
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stderr.expected $testroot/stderr
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + test_done "$testroot" "$ret"
> +}
> +
> +test_merge_adds_ignored_dangling_symlink() {
> + local testroot=`test_init merge_adds_ignored_dangling_symlink`
> + local commit0=`git_show_head $testroot/repo`
> + local commit0_author_time=`git_show_author_time $testroot/repo`
> +
> + git -C $testroot/repo checkout -q -b newbranch
> + echo "new file on branch" > $testroot/repo/gamma/new
> + git -C $testroot/repo add gamma/new > /dev/null
> + git_commit $testroot/repo -m "committing to new file on newbranch"
> + local branch_commit=`git_show_branch_head $testroot/repo newbranch`
> +
> + git -C $testroot/repo checkout -q master
> + echo gamma/new > $testroot/repo/.gitignore
> + git -C $testroot/repo add .gitignore > /dev/null
> + echo "ignoring new file on master branch" >
> $testroot/repo/epsilon/zeta
> + git_commit $testroot/repo -m "committing to zeta on master"
> + local master_commit=`git_show_head $testroot/repo`
> +
> + got checkout -b master $testroot/repo $testroot/wt > /dev/null
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + echo "got checkout failed unexpectedly" >&2
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + ln -f -s ../nonexistent $testroot/wt/gamma/new
> +
> + (cd $testroot/wt && got status > $testroot/stdout)
> +
> + echo -n > $testroot/stdout.expected
> +
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + (cd $testroot/wt && got status -I > $testroot/stdout)
> +
> + cat > $testroot/stdout.expected <<EOF
> +? gamma/new
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cat > $testroot/stderr.expected <<EOF
> +got: changes destined for some files were not yet merged and should be
> merged manually if required before the merge operation is continued
> +EOF
> + (cd $testroot/wt && got merge newbranch \
> + > $testroot/stdout 2> $testroot/stderr)
> + ret=$?
> + if [ $ret -eq 0 ]; then
> + echo "got merge succeeded unexpectedly" >&2
> + test_done "$testroot" "1"
> + return 1
> + fi
> +
> + local merge_commit=`git_show_head $testroot/repo`
> +
> + cat > $testroot/stdout.expected <<EOF
> +? gamma/new
> +Files not merged because an unversioned file was found in the work tree: 1
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cmp -s $testroot/stderr.expected $testroot/stderr
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stderr.expected $testroot/stderr
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + test_done "$testroot" "$ret"
> +}
> +
> +test_merge_adds_ignored_directory() {
> + local testroot=`test_init merge_adds_ignored_directory`
> + local commit0=`git_show_head $testroot/repo`
> + local commit0_author_time=`git_show_author_time $testroot/repo`
> +
> + git -C $testroot/repo checkout -q -b newbranch
> + echo "new file on branch" > $testroot/repo/gamma/new
> + git -C $testroot/repo add gamma/new > /dev/null
> + git_commit $testroot/repo -m "committing to new file on newbranch"
> + local branch_commit=`git_show_branch_head $testroot/repo newbranch`
> +
> + git -C $testroot/repo checkout -q master
> + echo gamma/new > $testroot/repo/.gitignore
> + git -C $testroot/repo add .gitignore > /dev/null
> + echo "ignoring new file on master branch" >
> $testroot/repo/epsilon/zeta
> + git_commit $testroot/repo -m "committing to zeta on master"
> + local master_commit=`git_show_head $testroot/repo`
> +
> + got checkout -b master $testroot/repo $testroot/wt > /dev/null
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + echo "got checkout failed unexpectedly" >&2
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + mkdir -p $testroot/wt/gamma/new/
> + echo 'this file is being ignored' > $testroot/wt/gamma/new/ignored
> +
> + (cd $testroot/wt && got status > $testroot/stdout)
> +
> + echo -n > $testroot/stdout.expected
> +
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + (cd $testroot/wt && got status -I > $testroot/stdout)
> +
> + cat > $testroot/stdout.expected <<EOF
> +? gamma/new/ignored
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cat > $testroot/stderr.expected <<EOF
> +got: changes destined for some files were not yet merged and should be
> merged manually if required before the merge operation is continued
> +EOF
> + (cd $testroot/wt && got merge newbranch \
> + > $testroot/stdout 2> $testroot/stderr)
> + ret=$?
> + if [ $ret -eq 0 ]; then
> + echo "got merge succeeded unexpectedly" >&2
> + test_done "$testroot" "1"
> + return 1
> + fi
> +
> + local merge_commit=`git_show_head $testroot/repo`
> +
> + cat > $testroot/stdout.expected <<EOF
> +~ gamma/new
> +File paths obstructed by a non-regular file: 1
> +EOF
> + cmp -s $testroot/stdout.expected $testroot/stdout
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stdout.expected $testroot/stdout
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + cmp -s $testroot/stderr.expected $testroot/stderr
> + ret=$?
> + if [ $ret -ne 0 ]; then
> + diff -u $testroot/stderr.expected $testroot/stderr
> + test_done "$testroot" "$ret"
> + return 1
> + fi
> +
> + test_done "$testroot" "$ret"
> +}
> +
> test_parseargs "$@"
> run_test test_merge_basic
> run_test test_merge_forward
> @@ -2352,3 +2713,7 @@ run_test test_merge_fetched_branch
> run_test test_merge_fetched_branch_remote
> run_test test_merge_tag
> run_test test_merge_tag_abort
> +run_test test_merge_adds_ignored_file
> +run_test test_merge_adds_ignored_symlink
> +run_test test_merge_adds_ignored_dangling_symlink
> +run_test test_merge_adds_ignored_directory
>
Got publishes local unversioned bytes during merge and rebase
Got publishes local unversioned bytes during merge and rebase
Got publishes local unversioned bytes during merge and rebase