git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Wanted - a file browser interface to git
@ 2005-10-19  0:58 John Ellson
  2005-10-19  1:07 ` Linus Torvalds
  0 siblings, 1 reply; 6+ messages in thread
From: John Ellson @ 2005-10-19  0:58 UTC (permalink / raw)
  To: git

I know that Linus thinks that files are less important than commits, but we are 
finding a real need to be able to browse though old versions of files and we 
have not yet found an efficient way to do it with git.

An example is:  "I know that file xxx contained algorithm yyy at some point in 
the past and now I'd like to browse back through the history of xxx to find the 
exact details."

I think what I'd like is a file browser on git that:

- can navigate the directory tree, starting by default with the HEAD
tree, but able to browse the state of the tree at any time in the history.

- can select any file from the tree, and then view the state of that file at any 
time in its history by stepping forward or back through commits that have 
affected that file.
	
- can view the difference between any pair of states of the file, with 
annotations as to the source of the changes.

- can search for a string across the complete history of a file.

- can invoke the users choice of editor on the file.


Neither gitk nor qgit provide tree browsing, so it can be hard to get at a
specific file.

qgit has nice file browser that annotates all changes, but I think I'd prefer a 
two panel diff view.

Neither qgit not gitk provide links to an editor so that a file can be worked on 
once found.


Am I out in left field here, or does anyone else feel the need for something 
like this?

John

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Wanted - a file browser interface to git
  2005-10-19  0:58 Wanted - a file browser interface to git John Ellson
@ 2005-10-19  1:07 ` Linus Torvalds
  2005-10-19  1:23   ` John Ellson
  2005-10-19  3:15   ` [PATCH] cg-history FILE [NTH_PARENT] - was: " John Ellson
  0 siblings, 2 replies; 6+ messages in thread
From: Linus Torvalds @ 2005-10-19  1:07 UTC (permalink / raw)
  To: John Ellson; +Cc: git



On Tue, 18 Oct 2005, John Ellson wrote:
> 
> An example is:  "I know that file xxx contained algorithm yyy at some point in
> the past and now I'd like to browse back through the history of xxx to find
> the exact details."

You are aware of "git whatchanged -p xxx", right?

Yeah, it's not graphical, and I agree that it might be very cool to have a 
graphical version of it. But I thought I'd mention it even so. A 
surprising number of people seem to have never realized, and at least for 
me personally, it's one of the most common things I do.

		Linus

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Wanted - a file browser interface to git
  2005-10-19  1:07 ` Linus Torvalds
@ 2005-10-19  1:23   ` John Ellson
  2005-10-19  3:03     ` Linus Torvalds
  2005-10-19  3:15   ` [PATCH] cg-history FILE [NTH_PARENT] - was: " John Ellson
  1 sibling, 1 reply; 6+ messages in thread
From: John Ellson @ 2005-10-19  1:23 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Linus Torvalds wrote:
> On Tue, 18 Oct 2005, John Ellson wrote:
>   
>> An example is:  "I know that file xxx contained algorithm yyy at some point in
>> the past and now I'd like to browse back through the history of xxx to find
>> the exact details."
>>     
>
> You are aware of "git whatchanged -p xxx", right?
>
> Yeah, it's not graphical, and I agree that it might be very cool to have a 
> graphical version of it. But I thought I'd mention it even so. A 
> surprising number of people seem to have never realized, and at least for 
> me personally, it's one of the most common things I do.
>
> 		Linus
>   
Linus,

I wasn't aware of it, no.  Looks very useful.  Thanks.

I see that you can take the tree id from the diff-tree lines and
then produce the state of the file at that time with "cg-admin-cat -r 
<id> xxx"
Is that how you would do it?

Are there any plans for cogito to support it?

John

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Wanted - a file browser interface to git
  2005-10-19  1:23   ` John Ellson
@ 2005-10-19  3:03     ` Linus Torvalds
  0 siblings, 0 replies; 6+ messages in thread
From: Linus Torvalds @ 2005-10-19  3:03 UTC (permalink / raw)
  To: John Ellson; +Cc: git



On Tue, 18 Oct 2005, John Ellson wrote:
> Linus Torvalds wrote:
> > 
> > You are aware of "git whatchanged -p xxx", right?
> 
> I wasn't aware of it, no.  Looks very useful.  Thanks.
> 
> I see that you can take the tree id from the diff-tree lines and
> then produce the state of the file at that time with "cg-admin-cat -r <id>
> xxx"
> Is that how you would do it?

Well, I'd do it with the git commands: once you see the diff, you should 
know the SHA1's of the source and destination, and then you can just do

	git-cat-file blob [sha1]

to get the before (or after) state.

The way I'd get the SHA1 is either (now with the extended diff format) in 
the short form from the diff itself (the "index" line), or by just 
separately doing a

	git-diff-tree -r [sha-of-commit]

to see the "raw" diff format.

All the diff things can take a pathname limiter, the same way 
"git-whatchanged" does, so if you are only interested in one file, just 
name the file:

	git-diff-tree -r [sha-of-commit] [filename]

And just to make clear how powerful this is: "filename" doesn't have to be 
a single file. It can be a set of files and/or directories, so if you want 
to track multiple things at the same time, just do multiple filenames.

What I do a lot is to check what has changed in some particular subsystem, 
ie somebody says that something broke in SCSI, and then I do

	git-whatchanged -p drivers/scsi/ include/scsi/

and it will show any changes to anything under either of those 
directories.

"git-whatchanged" really is very powerful. The silly thing is that it 
really boils down to just a single line script (well, with various 
argument handling etc it's actually five lines, but the "core" is really 
just a single pipeline of "git-rev-list | git-diff-tree --stdin".

> Are there any plans for cogito to support it?

Well, cogito could certainly just do a "cg-whatchanged", but it's really 
the same thing. Since cogito depends on git anyway, cogito users could 
just use the git-whatchanged functionality.

Or to make it more seamless, just do

	alias cg-whatchanged=git-whatchanged

or something like that ;^)

			Linus

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] cg-history FILE [NTH_PARENT]      - was: Re: Wanted - a file browser interface to git
  2005-10-19  1:07 ` Linus Torvalds
  2005-10-19  1:23   ` John Ellson
@ 2005-10-19  3:15   ` John Ellson
  2005-10-19  4:01     ` [PATCH] cg-history FILE [NTH_PARENT] Linus Torvalds
  1 sibling, 1 reply; 6+ messages in thread
From: John Ellson @ 2005-10-19  3:15 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Linus Torvalds wrote:
> 
> On Tue, 18 Oct 2005, John Ellson wrote:
>> An example is:  "I know that file xxx contained algorithm yyy at some point in
>> the past and now I'd like to browse back through the history of xxx to find
>> the exact details."
> 
> You are aware of "git whatchanged -p xxx", right?
> 
> Yeah, it's not graphical, and I agree that it might be very cool to have a 
> graphical version of it. But I thought I'd mention it even so. A 
> surprising number of people seem to have never realized, and at least for 
> me personally, it's one of the most common things I do.
> 
> 		Linus


OK.  Here is a not-very-smart cogito command to display the history of a file, 
or the state of the nth parent of the file in its history.

Feedback and or complete rewrites are requested ;-)

John


produce the history of a file, or its state at its nth_parent

---
commit 8478ad1164e37e9cca039a3f9552d2a98f7bead6
tree 40b39d5f9af573a7815f073cada03c7903bfc6fa
parent 5d74e4859afc81a4658133d5a83809ac814dbf34
author John Ellson <ellson@ontap.ellson.com> Tue, 18 Oct 2005 23:13:44 -0400
committer John Ellson <ellson@ontap.ellson.com> Tue, 18 Oct 2005 23:13:44 -0400

  cg-history |   36 ++++++++++++++++++++++++++++++++++++
  1 files changed, 36 insertions(+), 0 deletions(-)

diff --git a/cg-history b/cg-history
new file mode 100755
index 0000000..ba86f71
--- /dev/null
+++ b/cg-history
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+#
+# Display the change history of a file.
+# Copyright (c) John Ellson, 2005
+#
+# The change history of a file is displayed on stdout, or
+# if an integer is provided for NTH_PARENT, then the complete
+# state of the file at that step in its history is sent to stdout.
+#
+
+USAGE="cg-history FILE [NTH_PARENT]"
+
+. ${COGITO_LIB}cg-Xlib || exit 1
+
+[ "$ARGS" ] || usage
+
+if [ "${ARGS[1]}" = "" ]; then
+       git-whatchanged -p "${ARGS[0]}"
+else
+       i=0
+       git-whatchanged -p "${ARGS[0]}" |
+       while read -r cmd sha rest
+       do
+               case "$cmd" in
+               diff-tree)
+                       i=`expr $i + 1`
+                       if [ $i = ${ARGS[1]} ] ; then
+                               cg-admin-cat -r "$sha" "${ARGS[0]}"
+                               exit 0
+                       fi
+                       ;;
+               *)
+                       ;;
+               esac
+       done
+fi

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] cg-history FILE [NTH_PARENT]
  2005-10-19  3:15   ` [PATCH] cg-history FILE [NTH_PARENT] - was: " John Ellson
@ 2005-10-19  4:01     ` Linus Torvalds
  0 siblings, 0 replies; 6+ messages in thread
From: Linus Torvalds @ 2005-10-19  4:01 UTC (permalink / raw)
  To: John Ellson; +Cc: git


[ Ok, time for some serious power-git usage ]

On Tue, 18 Oct 2005, John Ellson wrote:
> 
> produce the history of a file, or its state at its nth_parent
>
> +       git-whatchanged -p "${ARGS[0]}" |

Actually, you're much better of _not_ using "-p" to generate a patch.

In fact, you don't even want the pretty format that "git-whatchanged" 
does, you really want the raw output.

Try this instead:

	git-rev-list HEAD | git-diff-tree --stdin -s -r "$ARG"

which will give _just_ a list of the commits that change the file "$ARG".

Here, the "--stdin" to git-diff-tree means that it should take its 
revision input from stdin (ie obvously the list of commits generated by 
git-rev-list), and the "-s" stands for "silent", ie git-diff-tree won't 
actually output the diff itself.

And the "-r" means that it should check the trees "recursively", which is 
needed since we want the diff-tree to traverse down the tree rather than 
just look at the top-level ("-p" to generate patches enables recursive by 
default since patches don't make sense on raw trees, but without the -p 
you need to do it explicitly).

And since we didn't ask for the header, the only thing you get is the list 
of commits that changed the file describled by the argument.

So now, you can just pick the n'th such commit, and do something like this

	#
	# Get the "${ARGS[1]}"th commit that changes  file "${ARGS[0]}"
	#
	rev=$(git-rev-list HEAD |
		git-diff-tree --stdin -s -r "${ARGS[0]}" |
		head -n "${ARGS[1]}" |
		tail -1)

	#
	# Pick up the file from that tree
	#
	filerev=$(git-ls-tree -r "$rev" "${ARGS[0]}" |
		cut -f1 |
		cut -d' ' -f3)

	#
	# And show it
	#
	git-cat-file blob $filerev

and you're done (untested, but you should get the idea).

Now, the interesting part about is that you can feed the output from 
git-diff-tree _back_ to git-diff-tree, so you can do some really fancy 
footwork like:

	git-rev-list rev1..rev2 |
		git-diff-tree --stdin -s -r "$ARG" |
		git-diff-tree --stdin -M --pretty -p

and what this will do is:

 - generate a list of all commits between rev1 and rev2

 - filter out just the commits that change the file "$ARG", and pass those 
   on.

 - for those commits, show the _whole_ diff, with rename detection and 
   with pretty-printed commit comment headers

In other words, you can basically look at all the full commits that 
changed one file (or a set of files). Efficiently.

This is kind of like "git-whatchanged", but it shows the full context of 
what changed. Of course, the second git-diff-tree can be used to limit the 
context to something else, ie you could do a variation of the above, 
something like

	git-rev-list v2.6.12.. |
		git-diff-tree --stdin -s -r drivers/usb/ |
		git-diff-tree --stdin -M --pretty -p drivers/ include/

which will show any commit that changed the drivers/usb/ directory after 
v2.6.12, but then limit the output of those commits to the drivers/ and 
include/ subdirectories (so anything that was changed in that same commit 
in a filesystem would _not_ be shown, for example, but if there were 
changes to drivers/scsi/ at the same time, they _would_ show).

Or, if you want to go really wild, do something like this on the kernel 
git tree:

	git-rev-list v2.6.12.. |
		git-diff-tree --stdin -s -r drivers/usb/ |
		git-diff-tree --stdin -s -r drivers/scsi/ |
		git-diff-tree --stdin -M --pretty -p drivers/scsi/ drivers/usb/ |
		less -S

which says to print out only those commits that change something _both_ in 
drivers/usb/ _and_ in drivers/scsi/ at the same time, and then show only 
those parts of the changes. 

Try it out. It really does work, and is extremely powerful. It's even 
pretty efficient (make sure your tree is packed first, though ;). I can do 
the above in about three seconds for the current kernel history on my 
machine. That's 3 _seconds_ to go through what right now is 8005 commits:

	git-rev-list v2.6.12.. | wc -l

and the reason is exactly that the filename-based parsing is very good at 
efficiently pruning out all the tree information that isn't needed.

Very cool.

However, the "normal" situation is just the standard "git-whatchanged", 
which is much easier to use than something more complex like the above.

The core git commands are really designed to be scriptable, but "real 
life" seldom wants the complexity of quite that much flexibility.

		Linus

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2005-10-19  4:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-10-19  0:58 Wanted - a file browser interface to git John Ellson
2005-10-19  1:07 ` Linus Torvalds
2005-10-19  1:23   ` John Ellson
2005-10-19  3:03     ` Linus Torvalds
2005-10-19  3:15   ` [PATCH] cg-history FILE [NTH_PARENT] - was: " John Ellson
2005-10-19  4:01     ` [PATCH] cg-history FILE [NTH_PARENT] Linus Torvalds

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).