threads / discuss / 20355

conflict status

Subject: conflict status

## tl;dr

8 messages between Aug 3, 2009 and Aug 4, 2009.

replies: 7people: 5as markdown or json

Michael Wild· Aug 3, 2009, 15:14 UTC · lore
Hi all

I'm merging two branches with a large number of conflicts. Fortunately, there are many modified/deleted conflicts (locally modified, remotely deleted), and I know that for those I want to pick the deleted version. However, I can't seem to motivate GIT into telling me for which of the conflicting files this is the case. I know that git-mergetool somehow extracts this information, but looking at the code, it seems to me that there must be an easier, user-level method of obtaining this information.

Generally speaking, I would like to know for each file with a conflict  
what it's status is, similar to what SVN does:
- locally modified/created/deleted/...
- remotely modified/created/deleted/...

Please excuse me if this is either trivial or has been answered many times before, but neither perusing the man-pages, nor asking google turned up anything remotely useful.

Thanks for the help
Michael
Sverre Rabbelier· Aug 3, 2009, 17:37 UTC · re: Michael Wild · lore

Re: conflict status

Heya,
On Mon, Aug 3, 2009 at 08:14, Michael Wild<themiwi@users.sourceforge.net> wrote:
> Generally speaking, I would like to know for each file with a conflict what
> it's status is, similar to what SVN does:
> - locally modified/created/deleted/...
> - remotely modified/created/deleted/...
Try 'git status' :),
-- 
Cheers,

Sverre Rabbelier
Thomas Rast· Aug 3, 2009, 18:17 UTC · re: Sverre Rabbelier · lore

Re: conflict status

You wrote:
Show 9 quoted lines
> Heya,
> 
> On Mon, Aug 3, 2009 at 08:14, Michael Wild<themiwi@users.sourceforge.net> wrote:
> > Generally speaking, I would like to know for each file with a conflict what
> > it's status is, similar to what SVN does:
> > - locally modified/created/deleted/...
> > - remotely modified/created/deleted/...
> 
> Try 'git status' :),
That only shows 'unmerged: foo' for me...

The closest to porcelain I can get while still having all the information is

  $ git ls-files -s foo
  100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 1       foo
  100644 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d 2       foo
In other words, not porcelain at all.

The third column is the stage: 1 for base, 2 for ours, 3 for theirs. So the above means that the file was changed between base and ours, and removed between base and theirs (as the entry is missing).

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
Junio C Hamano· Aug 3, 2009, 18:35 UTC · re: Thomas Rast · lore

Re: conflict status

Thomas Rast <trast@student.ethz.ch> writes:
Show 10 quoted lines
> That only shows 'unmerged: foo' for me...
>
> The closest to porcelain I can get while still having all the
> information is
>
>   $ git ls-files -s foo
>   100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 1       foo
>   100644 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d 2       foo
>
> In other words, not porcelain at all.

"git ls-files -u" would be what you want. It shows all the paths with conflicts in the index, and omits paths without conflicts in the index. And the object names allow you to inspect the individual stages.

Michael Wild· Aug 4, 2009, 07:10 UTC · re: Junio C Hamano · lore

Re: conflict status

On 3. Aug, 2009, at 20:35, Junio C Hamano wrote:
Show 18 quoted lines
> Thomas Rast <trast@student.ethz.ch> writes:
>
>> That only shows 'unmerged: foo' for me...
>>
>> The closest to porcelain I can get while still having all the
>> information is
>>
>>  $ git ls-files -s foo
>>  100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 1       foo
>>  100644 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d 2       foo
>>
>> In other words, not porcelain at all.
>
> "git ls-files -u" would be what you want.  It shows all the paths with
> conflicts in the index, and omits paths without conflicts in the  
> index.
> And the object names allow you to inspect the individual stages.
>

I found out about that one too (by having a look at git-mergetool), and came up with the following quick hack (doesn't take any arguments/ options, is very rough and slow for a large number of conflicts). For each unmerged file it displays the file name, prefixed with the local and remote state. Possible states are "c" for created, "m" for modified and "d" for deleted. Probably there are other cases I'm not aware of and require special handling.

#!/bin/sh # displays the merge status of files

# TODO all the niceties, bells and whistles...
USAGE=''
# requires PWD to be top-level
unset SUBDIRECTORY_OK
  . "$(git --exec-path)/git-sh-setup"
# obviously...
require_work_tree
# describe the state (deleted, modified or created)
describe_state () {
   mode="$1"
   if test -z "$mode"; then
     printf "d "
   else
     if test -n "$base_mode"; then
       printf "m "
     else
       printf "c "
     fi
   fi
}

# get all conflicts conflicts="$(git-status | awk '/unmerged:/{print $3;next}')"

for f in $conflicts; do
   # extract the file mode for base, local and remote
   base_mode=$(git ls-files -u -- "$f" | awk '{if ($3==1) print $1;}')
   local_mode=$(git ls-files -u -- "$f" | awk '{if ($3==2) print $1;}')
   remote_mode=$(git ls-files -u -- "$f" | awk '{if ($3==3) print $1;}')
   # create the status flags
   describe_state "$local_mode"
   describe_state "$remote_mode"
   # append the file name
   echo " $f"
done
Jakub Narebski· Aug 4, 2009, 07:19 UTC · re: Michael Wild · lore

Re: conflict status

Michael Wild <themiwi@users.sourceforge.net> writes:
Show 29 quoted lines
> On 3. Aug, 2009, at 20:35, Junio C Hamano wrote:
>> Thomas Rast <trast@student.ethz.ch> writes:
>>
>>> That only shows 'unmerged: foo' for me...
>>>
>>> The closest to porcelain I can get while still having all the
>>> information is
>>>
>>>  $ git ls-files -s foo
>>>  100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 1       foo
>>>  100644 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d 2       foo
>>>
>>> In other words, not porcelain at all.
>>
>> "git ls-files -u" would be what you want.  It shows all the paths with
>> conflicts in the index, and omits paths without conflicts in the
>> index.
>>
>> And the object names allow you to inspect the individual stages.
>>
> 
> 
> I found out about that one too (by having a look at git-mergetool),
> and came up with the following quick hack (doesn't take any arguments/
> options, is very rough and slow for a large number of conflicts). For
> each unmerged file it displays the file name, prefixed with the local
> and remote state. Possible states are "c" for created, "m" for
> modified and "d" for deleted. Probably there are other cases I'm not
> aware of and require special handling.

If you don't need SHA-1s, why not use -t or -v option of git-ls-files, e.g.:

  $ git ls-files -v -u
-- 
Jakub Narebski
Poland
ShadeHawk on #git
Michael Wild· Aug 4, 2009, 07:31 UTC · re: Jakub Narebski · lore

Re: conflict status

On 4. Aug, 2009, at 9:19, Jakub Narebski wrote:
Show 6 quoted lines
>
> If you don't need SHA-1s, why not use -t or -v option of git-ls-files,
> e.g.:
>
>  $ git ls-files -v -u
>

Huh? Sorry, I don't get your point. -v and -t will just prefix a "M" (or sometimes "m" in the case of-v) for unmerged files. But I already know they are unmerged, so why bother?

Junio C Hamano· Aug 4, 2009, 07:56 UTC · re: Michael Wild · lore

Re: conflict status

Michael Wild <themiwi@users.sourceforge.net> writes:
Show 14 quoted lines
> # get all conflicts
> conflicts="$(git-status | awk '/unmerged:/{print $3;next}')"
>
> for f in $conflicts; do
>   # extract the file mode for base, local and remote
>   base_mode=$(git ls-files -u -- "$f" | awk '{if ($3==1) print $1;}')
>   local_mode=$(git ls-files -u -- "$f" | awk '{if ($3==2) print $1;}')
>   remote_mode=$(git ls-files -u -- "$f" | awk '{if ($3==3) print $1;}')
>   # create the status flags
>   describe_state "$local_mode"
>   describe_state "$remote_mode"
>   # append the file name
>   echo " $f"
> done

Looks an awfully inefficient way to say "git ls-files -u" to me. If you do not see stage 2, you do not have it. If you do not see stage 3, they do not have it.

If you really really want to condense the object name information out, you could do something like this.

-- >8 --
#!/bin/sh
git ls-files -u -z |
perl -e '
	$/ = "\0";
        my ($last_path, @stage);
        sub describe_mode {
        	my $ours = $_[0];
		my $sign;
                if (!defined $ours) {
                	$sign = "d";
		} elsif (defined $stage[1]) {
                	$sign = "m";
		} else {
			$sign = "c";
                }
		return $sign;
        }
	sub flush_path {
        	printf("%s %s %s\n",
                	describe_mode($stage[2]),
                	describe_mode($stage[3]),
			$last_path);
		$last_path = undef;
        	@stage = ();
        }
        while (<>) {
		chomp;
        	my ($mode, $sha1, $stage, $path) =
                	/^([0-7]+) ([0-9a-f]{40}) ([1-3])\t(.*)$/;
		if (defined $last_path) {
			flush_path() if ($path ne $last_path);
                }
                $stage[$stage] = 1;
                $last_path = $path;
	}
        if (defined $last_path) {
                flush_path() if ($path ne $last_path);
        }
'
-- 8< --
I however do not think it is all that interesting, though.

← back to recent threads