threads / discuss / 2371

Expected Behavior?

Subject: Expected Behavior?

## tl;dr

3 messages between Nov 6, 2005 and Nov 7, 2005.

replies: 2people: 2as markdown or json

Jon Loeliger· Nov 6, 2005, 22:16 UTC · lore

I was working through some examples and found some rather curious behavior. I'm wondering if it is expected or not. This isn't quite minimal, but it is still small and shows the weirdness:

    git-init-db
    echo "Stuff for file1" > file1
    echo "Stuff for file2" > file2
    git add file1 file2
    git commit -m "Initial file1 and file2"
    git checkout -b dev
    echo "More for file1" >> file1
    rm -f file2
    echo "Another file!" > file3
    git update-index file1
    git update-index --force-remove file2
    git add file3
    git commit -m "Updated some stuff."
    git checkout master
    echo "Stuff for a conflict." >> file3
    git add file3
    git commit -m "Master update of file3"
    git merge "Grab dev stuff" master dev
Then, the part that I think is odd is demonstrated by "git status":
    $ git status
    #
    # Updated but not checked in:
    #   (will commit)
    #
    #       modified: file1
    #       deleted:  file2
    #       unmerged: file3
    #
    #
    # Changed but not updated:
    #   (use git-update-index to mark for commit)
    #
    #       unmerged: file3
    #
    #
    # Untracked files:
    #   (use "git add" to add to commit)
    #
    #       file3

Why is file3 considered untracked and needing to be added? It was present in both "dev" and "master" branches before the merge. It doesn't end up with "<<< one === other >>>" style diffs either.

My guess is that the file is small, one line, in each branch. When the diff happens, it sees the file as empty in the other branch and considers that "new" directly, rather than asking the index if it knows about it to determine "newness" status.

Or perhaps it is that the file became new in each branch independently and never really had a true common ancestor.

Thanks, jdl

Junio C Hamano· Nov 7, 2005, 01:38 UTC · re: Jon Loeliger · lore

Re: Expected Behavior?

Jon Loeliger <jdl@freescale.com> writes:
Show 9 quoted lines
>     # Untracked files:
>     #   (use "git add" to add to commit)
>     #
>     #       file3
>
> Why is file3 considered untracked and needing to be added?
> It was present in both "dev" and "master" branches before
> the merge.  It doesn't end up with "<<< one === other >>>"
> style diffs either.

It is because Untracked uses different program than git-diff-* and, it mishandles unmerged paths. Let me see...

Yup, it uses "git-ls-files --others", which considers that unmerged paths do not "exist" in the index. This is wrong.

The attached is a patch to fix ls-files.

I also think that file3 should not appear in "Updated but not checked in (will commit)" list -- we are _not_ going to commit unmerged paths until you tell git what you want to do with them. The patch in the next message fixes it.

-- >8 -- cut here -- >8 --
Subject: ls-files: --others should not say unmerged paths are unknown.

Jon Loeliger noticed that an unmerged path appears as "Untracked" in git-status output, even though we show the same path as updated/changed. Since --others means "we have not told git about that path", we should not show unmerged paths -- obviously, git knows about them; it just does not know what we want to do about them yet.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---
 ls-files.c |   26 ++++++++++++++++++++++++--
 1 files changed, 24 insertions(+), 2 deletions(-)

applies-to: f571975209b0bc38ca099684f9731efe4163b396 fcbc3083e37f3c025d85d7b2c8a1c53d07a81fac

diff --git a/ls-files.c b/ls-files.c
index d9c8b21..f7653e7 100644
--- a/ls-files.c
+++ b/ls-files.c
@@ -348,6 +348,29 @@ static void show_dir_entry(const char *t
 	putchar(line_terminator);
 }
 
+static void show_other_files(void)
+{
+	int i;
+	for (i = 0; i < nr_dir; i++) {
+		/* We should not have a matching entry, but we
+		 * may have an unmerged entry for this path.
+		 */
+		struct nond_on_fs *ent = dir[i];
+		int pos = cache_name_pos(ent->name, ent->len);
+		struct cache_entry *ce;
+		if (0 <= pos)
+			die("bug in show-other-files");
+		pos = -pos - 1;
+		if (pos < active_nr) { 
+			ce = active_cache[pos];
+			if (ce_namelen(ce) == ent->len &&
+			    !memcmp(ce->name, ent->name, ent->len))
+				continue; /* Yup, this one exists unmerged */
+		}
+		show_dir_entry(tag_other, ent);
+	}
+}
+
 static void show_killed_files(void)
 {
 	int i;
@@ -438,8 +461,7 @@ static void show_files(void)
 		read_directory(path, base, baselen);
 		qsort(dir, nr_dir, sizeof(struct nond_on_fs *), cmp_name);
 		if (show_others)
-			for (i = 0; i < nr_dir; i++)
-				show_dir_entry(tag_other, dir[i]);
+			show_other_files();
 		if (show_killed)
 			show_killed_files();
 	}
---
0.99.9.GIT
Junio C Hamano· Nov 7, 2005, 02:01 UTC · re: Jon Loeliger · lore

Re: Expected Behavior?

Jon Loeliger <jdl@freescale.com> writes:
Show 9 quoted lines
>     git checkout -b dev
>
>     echo "More for file1" >> file1
>     rm -f file2
>     echo "Another file!" > file3
>
>     git update-index file1
>     git update-index --force-remove file2
>     git add file3

You do not have file2 in the working tree, so regular --remove would do.

	git-update-index --add --remove file1 file2 file3
>     git merge "Grab dev stuff" master dev

This is good. We used to use (and the tutorial only talks about) git-resolve to do this step, like this:

	git-resolve master dev 'Merge dev branch'

And I've kept using git-resolve myself; not that I do not trust git-merge but purely from inertia, although I was the one who did 'git merge' ;-). Maybe I should first update the tutorial to use git-merge instead of git-resolve.

It appears that as the everyday workhorse, using Daniel's git-merge-resolve is stable through git-merge have proven stable enough. So here is a question. Do people mind if 'git-resolve' and 'git-octopus' are dropped before 1.0? This means 2 less programs in your /usr/bin ;-).

← back to recent threads