[PATCH] better git-submodule status output

Subsystems: documentation, the rest

STALE3712d

7 messages, 3 authors, 2016-06-15 · open the first message on its own page

[PATCH] better git-submodule status output

From: Sylvain Joyeux <hidden>
Date: 2016-06-15 22:44:52

Oups.. sorry for the patch-as-attachment in the previous mail

This patch makes the output of git-submodule more useful to handle the
management of a repository using multiple submodules. Namely, it
displays informations about how the current checked out version relates
to the registered one (i.e. direct parent, direct child, "just
different", registered revision does not exist), and displays if the
submodules contain uncommitted changes.

This (among other things) allows to do git-submodule update while
knowing exactly what will happen.
--
Sylvain
From 16553a9b210a956b0af961d55a9cf06f1b9b8114 Mon Sep 17 00:00:00 2001
From: Sylvain Joyeux <redacted>
Date: Tue, 1 Jul 2008 16:01:01 +0200
Subject: [PATCH] more information in git-submodule status output

This commit adds more information in the 'status' output of
git-submodule. More specifically, it displays different flags if the
submodule and the registered revision are direct parents (> and <,
depending on which is the ancestor), if they are not direct parents (+)
or if the registered revision cannot be found (i.e. if submodule update
would fail, '!')

Finally, it shows if the submodule contains uncommitted changes (M flag)

Signed-off-by: Sylvain Joyeux <redacted>
---
 Documentation/git-submodule.txt |   23 ++++++++++++++++++-----
 git-submodule.sh                |   32 ++++++++++++++++++++++++++++----
 t/t7400-submodule-basic.sh      |   20 +++++++++++++-------
 3 files changed, 59 insertions(+), 16 deletions(-)
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 441ae14..3820002 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -33,10 +33,23 @@ status::
 	Show the status of the submodules. This will print the SHA-1 of the
 	currently checked out commit for each submodule, along with the
 	submodule path and the output of linkgit:git-describe[1] for the
-	SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
-	initialized and `+` if the currently checked out submodule commit
-	does not match the SHA-1 found in the index of the containing
-	repository. This command is the default command for git-submodule.
+	SHA-1. Each SHA-1 will be prefixed with the following codes:
+	* `-` if the submodule is not initialized
+	* `<` if the current submodule HEAD is a direct ancestor of the
+	    revision registered in the containing repository.  I.e. a `git
+	    submodule update` would lead to a fast forward.
+	* `>` if the current submodule HEAD is a direct ancestor of the
+	    revision registered in the containing repository.
+	* `+` if the current submodule HEAD and the revision registered in
+	    the containing repository do not match, and there is no direct
+	    relationship between the two commits.
+	* `!` if the SHA-1 found in the index of the containing repository is
+	    not present in the the currently checked out submodule commit,
+	    nor be fetched from the associated remote.
+	
+	Additionally, a 'M' is displayed if the currently checked out
+	submodule contains uncommitted changes.
+	This command is the default command for git-submodule.
 
 init::
 	Initialize the submodules, i.e. register in .git/config each submodule
@@ -97,7 +110,7 @@ for details.
 
 AUTHOR
 ------
-Written by Lars Hjemli <hjemli@gmail.com>
+Written by Lars Hjemli <hjemli@gmail.com> and Sylvain Joyeux <sylvain.joyeux@m4x.org>
 
 GIT
 ---
diff --git a/git-submodule.sh b/git-submodule.sh
index 3eb78cc..e2b91f6 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -522,7 +522,11 @@ cmd_summary() {
 #
 # List all submodules, prefixed with:
 #  - submodule not initialized
-#  + different revision checked out
+#  > the checked out version is in advance with the current version (fast-forward)
+#  < the checked out version is late w.r.t the current version (fast-forward)
+#  + different revisions checked out, no fast-forward relationship
+#  ! the checked out version does not exist and cannot be fetched
+#  M submodule contains uncommitted changes
 #
 # If --cached was specified the revision in the index will be printed
 # instead of the currently checked out revision.
@@ -562,20 +566,40 @@ cmd_status()
 		url=$(git config submodule."$name".url)
 		if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
 		then
-			say "-$sha1 $path"
+			say "-  $sha1 $path"
 			continue;
 		fi
+                unclean=" "
+                if ! ( unset GIT_DIR; cd "$path" && git diff --quiet HEAD ); then
+                    unclean="M"
+                fi
 		set_name_rev "$path" "$sha1"
 		if git diff-files --quiet -- "$path"
 		then
-			say " $sha1 $path$revname"
+			say " $unclean $sha1 $path$revname"
 		else
+                        head=$(unset GIT_DIR; cd "$path" && git rev-parse --verify HEAD)
+                        common=$(unset GIT_DIR; cd "$path" && git merge-base HEAD $sha1)
+                        if test -z "$common"; then
+                            common=$(unset GIT_DIR; cd "$path" && git-fetch -q &&
+                                    git merge-base HEAD $sha1)
+                        fi
+                        if test "$common" = "$sha1"; then
+                            modflag=">"
+                        elif test "$common" = "$head"; then
+                            modflag="<"
+                        elif test "$common" = ""; then
+                            modflag="!"
+                        else
+                            modflag="+"
+                        fi
+
 			if test -z "$cached"
 			then
 				sha1=$(unset GIT_DIR; cd "$path" && git rev-parse --verify HEAD)
 				set_name_rev "$path" "$sha1"
 			fi
-			say "+$sha1 $path$revname"
+			say "$modflag$unclean $sha1 $path$revname"
 		fi
 	done
 }
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index 6c7b902..ffaa932 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -65,7 +65,7 @@ test_expect_success 'status should only print one line' '
 '
 
 test_expect_success 'status should initially be "missing"' '
-	git-submodule status | grep "^-$rev1"
+	git-submodule status | grep "^-  $rev1"
 '
 
 test_expect_success 'init should register submodule url in .git/config' '
@@ -130,13 +130,19 @@ test_expect_success 'update should work when path is an empty dir' '
 '
 
 test_expect_success 'status should be "up-to-date" after update' '
-	git-submodule status | grep "^ $rev1"
+	git-submodule status | grep "^   $rev1"
 '
 
-test_expect_success 'status should be "modified" after submodule commit' '
+test_expect_success 'status should be "modified" after submodule change' '
 	cd init &&
 	echo b >b &&
-	git add b &&
+        git add b &&
+        cd .. &&
+	git-submodule status | grep "^ M $rev1"
+'
+
+test_expect_success 'status should be "in advance" after submodule commit' '
+	cd init &&
 	git-commit -m "submodule commit 2" &&
 	rev2=$(git rev-parse HEAD) &&
 	cd .. &&
@@ -145,11 +151,11 @@ test_expect_success 'status should be "modified" after submodule commit' '
 		echo "[OOPS] submodule git rev-parse returned nothing"
 		false
 	fi &&
-	git-submodule status | grep "^+$rev2"
+	git-submodule status | grep "^>  $rev2"
 '
 
 test_expect_success 'the --cached sha1 should be rev1' '
-	git-submodule --cached status | grep "^+$rev1"
+	git-submodule --cached status | grep "^>  $rev1"
 '
 
 test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
@@ -171,7 +177,7 @@ test_expect_success 'update should checkout rev1' '
 '
 
 test_expect_success 'status should be "up-to-date" after update' '
-	git-submodule status | grep "^ $rev1"
+	git-submodule status | grep "^   $rev1"
 '
 
 test_expect_success 'checkout superproject with subproject already present' '
-- 
1.5.6

Re: [PATCH] better git-submodule status output

From: Sylvain Joyeux <hidden>
Date: 2016-06-15 22:44:54

Here is a (tentative) summary of the whole discussion:

* doing fetch in status is EVIL. Therefore, status should only report
  whatever information is available.
* nonetheless, having a "peek" mode seem to be accepted as a useful
  feature not only by me.
* changing the output format of git-submodules is not right either,
  because it would break existing tools which parses it at the moment.

Proposal
- remove fetch from status, and make the new output enabled when
  --verbose is set (can also be set in the config file I guess).

  On the symbols side, I propose:
    > submodule commit is a direct descendant of the commit in the
      superproject
    < submodule commit is a direct ancestor of the commit in the
      superproject
    + no direct relation between submodule commit and commit in the
      superproject
    ? the commit in the superproject cannot be found in the submodule
      (replaces the initial '!' in my patch)

  A 'M' is appended if the submodule has uncommitted changes

- define a git-submodule 'fetch' subcommand which call fetch in each
  submodule and runs the verbose mode of git-status (can be disabled by
  a --quiet option).

Comments ? (I'm sure there are some ...)

Sylvain

Re: [PATCH] better git-submodule status output

From: Andreas Ericsson <hidden>
Date: 2016-06-15 22:44:54

Sylvain Joyeux wrote:
Here is a (tentative) summary of the whole discussion:

* doing fetch in status is EVIL. Therefore, status should only report
  whatever information is available.
* nonetheless, having a "peek" mode seem to be accepted as a useful
  feature not only by me.
* changing the output format of git-submodules is not right either,
  because it would break existing tools which parses it at the moment.

Proposal
- remove fetch from status, and make the new output enabled when
  --verbose is set (can also be set in the config file I guess).

  On the symbols side, I propose:
    > submodule commit is a direct descendant of the commit in the
      superproject
    < submodule commit is a direct ancestor of the commit in the
      superproject
    + no direct relation between submodule commit and commit in the
      superproject
    ? the commit in the superproject cannot be found in the submodule
      (replaces the initial '!' in my patch)

  A 'M' is appended if the submodule has uncommitted changes

- define a git-submodule 'fetch' subcommand which call fetch in each
  submodule and runs the verbose mode of git-status (can be disabled by
  a --quiet option).

Comments ? (I'm sure there are some ...)
Re-use the existing symbolism from fetch status output. Using '+' to
denote "no direct relation" in a tool that shows patches half the
time is just plain horrible.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

Re: [PATCH] better git-submodule status output

From: Sylvain Joyeux <hidden>
Date: 2016-06-15 22:44:54

On Wed, Jul 09, 2008 at 12:25:25PM +0200, Andreas Ericsson wrote:
Sylvain Joyeux wrote:
quoted
Here is a (tentative) summary of the whole discussion:

* doing fetch in status is EVIL. Therefore, status should only report
  whatever information is available.
* nonetheless, having a "peek" mode seem to be accepted as a useful
  feature not only by me.
* changing the output format of git-submodules is not right either,
  because it would break existing tools which parses it at the moment.

Proposal
- remove fetch from status, and make the new output enabled when
  --verbose is set (can also be set in the config file I guess).

  On the symbols side, I propose:
    > submodule commit is a direct descendant of the commit in the
      superproject
    < submodule commit is a direct ancestor of the commit in the
      superproject
    + no direct relation between submodule commit and commit in the
      superproject
    ? the commit in the superproject cannot be found in the submodule
      (replaces the initial '!' in my patch)

  A 'M' is appended if the submodule has uncommitted changes

- define a git-submodule 'fetch' subcommand which call fetch in each
  submodule and runs the verbose mode of git-status (can be disabled by
  a --quiet option).

Comments ? (I'm sure there are some ...)
Re-use the existing symbolism from fetch status output. Using '+' to
denote "no direct relation" in a tool that shows patches half the
time is just plain horrible.
Could you be more specific ? AFAIK, 'fetch' symbolism is based on files,
the one I need is comparing commits.

And I don't like the '+' either. I chose it because it is the current
symbol to show that there is a difference between
superproject/submodule.
-- 
=======================================================================
Dr. Ing. Sylvain Joyeux                          sylvain.joyeux@dfki.de
Researcher
DFKI Robotik Lab -- Bremen                   http://www.dfki.de/robotik
Tel: 0049 421 218 64136
=======================================================================

Re: [PATCH] better git-submodule status output

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:44:54

Hi,

On Wed, 9 Jul 2008, Sylvain Joyeux wrote:
  On the symbols side, I propose:
    > submodule commit is a direct descendant of the commit in the
      superproject
    < submodule commit is a direct ancestor of the commit in the
      superproject
    + no direct relation between submodule commit and commit in the
      superproject
    ? the commit in the superproject cannot be found in the submodule
      (replaces the initial '!' in my patch)
I like the output of "git checkout" when your local branch is not agreeing 
with the tracked branch.  Maybe it would be more user-friendly to have 
submodule use that type of message, instead of cryptic single letter?

On a related note, the long commit name has been a constant nuisance for 
me.  A short commit name is perfectly enough, methinks.
- define a git-submodule 'fetch' subcommand which call fetch in each
  submodule and runs the verbose mode of git-status (can be disabled by
  a --quiet option).
I like it.

You probably can refactor the code for "update" to do that nicely.

Ciao,
Dscho

Re: [PATCH] better git-submodule status output

From: Sylvain Joyeux <hidden>
Date: 2016-06-15 22:44:55

quoted
  On the symbols side, I propose:
    > submodule commit is a direct descendant of the commit in the
      superproject
    < submodule commit is a direct ancestor of the commit in the
      superproject
    + no direct relation between submodule commit and commit in the
      superproject
    ? the commit in the superproject cannot be found in the submodule
      (replaces the initial '!' in my patch)
I like the output of "git checkout" when your local branch is not agreeing 
with the tracked branch.  Maybe it would be more user-friendly to have 
submodule use that type of message, instead of cryptic single letter?
Mmmm ... Yes that could be a great idea. I'll try it.
 
On a related note, the long commit name has been a constant nuisance for 
me.  A short commit name is perfectly enough, methinks.
I also think so. The commit ID is completely useless for humans.
Nonetheless, that would change the git-submodules output which
(according to someone-that-I-dont-remember) would be a Bad Thing(tm).
quoted
- define a git-submodule 'fetch' subcommand which call fetch in each
  submodule and runs the verbose mode of git-status (can be disabled by
  a --quiet option).
I like it.

You probably can refactor the code for "update" to do that nicely.
OK

Sylvain

Re: [PATCH] better git-submodule status output

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:44:55

Hi,

On Wed, 9 Jul 2008, Sylvain Joyeux wrote:
[Sylvain quoted somebody, but found it funny to let the reader guess]
quoted
On a related note, the long commit name has been a constant nuisance 
for me.  A short commit name is perfectly enough, methinks.
I also think so. The commit ID is completely useless for humans. 
Nonetheless, that would change the git-submodules output which 
(according to someone-that-I-dont-remember) would be a Bad Thing(tm).
Is git-submodule supposed to be plumbing?  I don't think so.

Ciao,
Dscho
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help