* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Johannes Schindelin @ 2007-10-25 10:27 UTC (permalink / raw)
To: Steffen Prohaska
Cc: Peter Baumann, Andreas Ericsson, J. Bruce Fields, Jakub Narebski,
Federico Mena Quintero, git
In-Reply-To: <79366145-3C91-4417-B62C-FFF9EC452076@zib.de>
Hi,
On Thu, 25 Oct 2007, Steffen Prohaska wrote:
> On Oct 25, 2007, at 1:28 AM, Johannes Schindelin wrote:
>
> > On Thu, 25 Oct 2007, Steffen Prohaska wrote:
> >
> > > On Oct 25, 2007, at 12:14 AM, Johannes Schindelin wrote:
> > >
> > > > But I think I have to drive my message home again: if what you
> > > > desire becomes reality, you take away the clear distinction
> > > > between local and remote branches. In fact, those branches are
> > > > neither local (because the next pull will automatically update
> > > > them with remote changes, but _only_ if they fast-forward) nor
> > > > remote (because you plan to work on them locally).
> > >
> > > Exactly, because I do not work on those branches alone. These are
> > > _shared_ branches. I can work on such a branch with a group of
> > > developers. I'm willing to accept this bit of chaos.
> >
> > It is not just a chaos. I see a serious problem here. On _your_
> > computer, you do _not_ have a shared branch. Which is visible _even_
> > in your modified work flow when you have unpushed changes.
> >
> > So your desired illusion that your local branches are anything but
> > local branches will never be perfect enough.
>
> Ok, there is not a fundamental difference between local branches
> that automatically merge from remotes and local branches that
> are purely local and _never_ merge anything automatically. Both
> are only local branches.
Actually, not really. For refs/remotes/* you expect them to change
possibly at the same time. For your local branches, I'd expect them only
to change when I am actually working on them (and yes, that includes a
pull into the current branch).
> > > Your rebase workflow is not possible if more than one dev wants to
> > > work on the topic branch together.
> >
> > Why not? I do it all the time. CVS users do it all the time, for
> > that matter.
>
> You're right. You can rebase your local changes on top of the new shared
> remote head. And this is probably the best thing you can do to get a
> clean history. Maybe it should be easier.
It should. Thus my question about best practices (which is technically in
this thread, but we are in a subthread which permuted into "I want git
pull to behave differently")
I _want_ this to be easier.
> So, do I understand correctly, what you propose is:
> - never merge but only rebase
> - Due to lacking support for this in "git pull", never use
> git pull when working with shared branches but instead _always_ use
> "git fetch; git rebase origin/<branch_I'm_on>".
>
> So you say that one of the first messages in "git for CVS users", "The
> equivalent of cvs update is git pull origin" [1], is wrong. I don't
> think I'm able to sell your proposed workflow with the current
> documentation. But maybe I try if I'm absolutely convinced that it is
> superior.
Hehe. You just experienced the tremendous speed at which git moves. In
the beginning, we really thought that "git pull" is all you'll ever want
to have.
But in the meantime, one of the biggest Enemies of the Rebase (yours
truly) converted to an avid fan of it, because it really helps
development. It also makes for clean history, which is always good.
> > > > But here is a proposal which should make you and your developers
> > > > happy, _and_ should be even easier to explain:
> > > >
> > > > Work with topic branches. And when you're done, delete them.
> > >
> > > Again, if you want to share the topic branch the situation gets more
> > > complex.
> >
> > Hardly so. In my proposed solution to your problem, there is nothing
> > which prevents you from working off of another branch than "master".
>
> Well if you have several local branches checked out that are
> shared with others you run into the "git push" problem again ...
> (see below at git push origin master).
Do the same as I, always say "git push origin master" (of course, you
should exchange "master" with whatever branch you want to push). Be
precise.
> > > > So the beginning of the day could look like this:
> > > >
> > > > git fetch
> > > > git checkout -b todays-topic origin/master
> > > >
> > > > [hack hack hack]
> > > > [test test test]
> > > > [debug debug debug]
> > > > [occasionally commit]
> > > > [occasionally git rebase -i origin/master]
> > > >
> > > > and the end of the topic
> > > >
> > > > git branch -M master
>
> Isn't this a bit dangerous? It forces to overwrite master no matter
> what's on it. You don't see diffstats nor a fast forward message that
> confirms what you're doing.
Yeah, I should have said something like "git branch -m master"
(implicitely assuming that you have no current "master" branch).
> > > > git push origin master
>
> I'd like to see "git push" here.
I think it is not asking too much for the user to be a bit more precise.
If you really do not trust your developers to be capable of that, point
them to git gui.
> git branch -m <shared_branch>
> git push origin <shared_branch>
> git checkout do-not-work-here
> git branch -D <shared_branch>
Actually, the last two commands would better be
git checkout HEAD^{commit}
git branch -d <shared_branch>
> > The problem I see here: you know git quite well. Others don't, and
> > will be mightily confused why pull updates local branches sometimes,
> > and sometimes not.
>
> But it already happens now. "git pull" sometimes merges a remote branch
> (--track) and sometimes it reports an error that is fails to do so
> (--no-track).
If there really is an inconsistent behaviour, then we'll have to fix that.
We should not introduce inconsistent behaviour on top of that.
Ciao,
Dscho
^ permalink raw reply
* [PATCH 9/9] git-svn: Make fetch ~1.7x faster
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben, Eric Wong
In-Reply-To: <1193307927-3592-9-git-send-email-aroben@apple.com>
We were spending a lot of time forking/execing git-cat-file and
git-hash-object. We now maintain a global Git repository object in order to use
Git.pm's more efficient hash_and_insert_object and cat_blob methods.
Signed-off-by: Adam Roben <aroben@apple.com>
---
Eric Wong wrote:
> > +sub hash_object {
> > + my (undef, $fh) = @_;
> > +
> > + my ($tmp_fh, $tmp_filename) = tempfile(UNLINK => 1);
> > + while (my $line = <$fh>) {
> > + print $tmp_fh $line;
> > + }
> > + close($tmp_fh);
>
> Related to the above. It's better to sysread()/syswrite() or
> read()/print() in a loop with a predefined buffer size rather than to
> use a readline() since you could be dealing with files with very long
> lines or binaries with no newline characters in them at all.
Fixed.
> > + _open_hash_object_if_needed();
> > + print $_hash_object_out $tmp_filename . "\n";
>
> Minor, but
>
> print $_hash_object_out $tmp_filename, "\n";
>
> avoids creating a new string.
Fixed.
git-svn.perl | 40 ++++++++++++++++++----------------------
1 files changed, 18 insertions(+), 22 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 22bb47b..fcb07f5 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -4,7 +4,7 @@
use warnings;
use strict;
use vars qw/ $AUTHOR $VERSION
- $sha1 $sha1_short $_revision
+ $sha1 $sha1_short $_revision $_repository
$_q $_authors %users/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '@@GIT_VERSION@@';
@@ -225,6 +225,7 @@ unless ($cmd =~ /(?:clone|init|multi-init)$/) {
}
$ENV{GIT_DIR} = $git_dir;
}
+ $_repository = Git->repository(Repository => $ENV{GIT_DIR});
}
unless ($cmd =~ /^(?:clone|init|multi-init|commit-diff)$/) {
Git::SVN::Migration::migration_check();
@@ -332,6 +333,7 @@ sub cmd_init {
"as a command-line argument\n";
init_subdir(@_);
do_git_init_db();
+ $_repository = Git->repository(Repository => $ENV{GIT_DIR});
Git::SVN->init($url);
}
@@ -2541,6 +2543,7 @@ use vars qw/@ISA/;
use strict;
use warnings;
use Carp qw/croak/;
+use File::Temp qw/tempfile/;
use IO::File qw//;
use Digest::MD5;
@@ -2683,14 +2686,8 @@ sub apply_textdelta {
my $base = IO::File->new_tmpfile;
$base->autoflush(1);
if ($fb->{blob}) {
- defined (my $pid = fork) or croak $!;
- if (!$pid) {
- open STDOUT, '>&', $base or croak $!;
- print STDOUT 'link ' if ($fb->{mode_a} == 120000);
- exec qw/git-cat-file blob/, $fb->{blob} or croak $!;
- }
- waitpid $pid, 0;
- croak $? if $?;
+ my $contents = $::_repository->cat_blob($fb->{blob});
+ print $base $contents;
if (defined $exp) {
seek $base, 0, 0 or croak $!;
@@ -2729,14 +2726,18 @@ sub close_file {
$buf eq 'link ' or die "$path has mode 120000",
"but is not a link\n";
}
- defined(my $pid = open my $out,'-|') or die "Can't fork: $!\n";
- if (!$pid) {
- open STDIN, '<&', $fh or croak $!;
- exec qw/git-hash-object -w --stdin/ or croak $!;
+
+ my ($tmp_fh, $tmp_filename) = File::Temp::tempfile(UNLINK => 1);
+ my $result;
+ while ($result = sysread($fh, my $string, 1024)) {
+ syswrite($tmp_fh, $string, $result);
}
- chomp($hash = do { local $/; <$out> });
- close $out or croak $!;
+ defined $result or croak $!;
+ close $tmp_fh or croak $!;
+
close $fh or croak $!;
+
+ $hash = $::_repository->hash_and_insert_object($tmp_filename);
$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
close $fb->{base} or croak $!;
} else {
@@ -3063,13 +3064,8 @@ sub chg_file {
} elsif ($m->{mode_a} =~ /^120/ && $m->{mode_b} !~ /^120/) {
$self->change_file_prop($fbat,'svn:special',undef);
}
- defined(my $pid = fork) or croak $!;
- if (!$pid) {
- open STDOUT, '>&', $fh or croak $!;
- exec qw/git-cat-file blob/, $m->{sha1_b} or croak $!;
- }
- waitpid $pid, 0;
- croak $? if $?;
+ my $blob = $::_repository->cat_blob($m->{sha1_b});
+ print $fh $blob;
$fh->flush == 0 or croak $!;
seek $fh, 0, 0 or croak $!;
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [PATCH 8/9] Git.pm: Add hash_and_insert_object and cat_blob
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben, Eric Wong
In-Reply-To: <1193307927-3592-8-git-send-email-aroben@apple.com>
These functions are more efficient ways of executing `git hash-object -w` and
`git cat-file blob` when you are dealing with many files/objects.
Signed-off-by: Adam Roben <aroben@apple.com>
---
Eric Wong wrote:
> > +package Git::Commands;
>
> Can this be a separate file, or a part of Git.pm? I'm sure other
> scripts can eventually use this and I've been meaning to split
> git-svn.perl into separate files so it's easier to follow.
I ended up making it part of Git.pm, because I realized that made far more
sense than splitting it into a separate file.
perl/Git.pm | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 95 insertions(+), 2 deletions(-)
diff --git a/perl/Git.pm b/perl/Git.pm
index 46c5d10..f23edef 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -39,6 +39,9 @@ $VERSION = '0.01';
my $lastrev = $repo->command_oneline( [ 'rev-list', '--all' ],
STDERR => 0 );
+ my $sha1 = $repo->hash_and_insert_object('file.txt');
+ my $contents = $repo->cat_blob($sha1);
+
=cut
@@ -218,7 +221,6 @@ sub repository {
bless $self, $class;
}
-
=back
=head1 METHODS
@@ -675,6 +677,93 @@ sub hash_object {
}
+=item hash_and_insert_object ( FILENAME )
+
+Compute the SHA1 object id of the given C<FILENAME> and add the object to the
+object database.
+
+The function returns the SHA1 hash.
+
+=cut
+
+# TODO: Support for passing FILEHANDLE instead of FILENAME
+sub hash_and_insert_object {
+ my ($self, $filename) = @_;
+
+ $self->_open_hash_and_insert_object_if_needed();
+ my ($in, $out) = ($self->{hash_object_in}, $self->{hash_object_out});
+
+ print $out $filename, "\n";
+ chomp(my $hash = <$in>);
+ return $hash;
+}
+
+sub _open_hash_and_insert_object_if_needed {
+ my ($self) = @_;
+
+ return if defined($self->{hash_object_pid});
+
+ ($self->{hash_object_pid}, $self->{hash_object_in},
+ $self->{hash_object_out}, $self->{hash_object_ctx}) =
+ command_bidi_pipe(qw(hash-object -w --stdin-paths));
+}
+
+sub _close_hash_and_insert_object {
+ my ($self) = @_;
+
+ return unless defined($self->{hash_object_pid});
+
+ my @vars = map { 'hash_object' . $_ } qw(pid in out ctx);
+
+ command_close_bidi_pipe($self->{@vars});
+ delete $self->{@vars};
+}
+
+=item cat_blob ( SHA1 )
+
+Returns the contents of the blob identified by C<SHA1>.
+
+=cut
+
+sub cat_blob {
+ my ($self, $sha1) = @_;
+
+ $self->_open_cat_blob_if_needed();
+ my ($in, $out) = ($self->{cat_blob_in}, $self->{cat_blob_out});
+
+ print $out $sha1, "\n";
+ chomp(my $size = <$in>);
+
+ my $blob;
+ my $result = read($in, $blob, $size);
+ defined $result or carp $!;
+
+ # Skip past the trailing newline.
+ read($in, my $newline, 1);
+
+ return $blob;
+}
+
+sub _open_cat_blob_if_needed {
+ my ($self) = @_;
+
+ return if defined($self->{cat_blob_pid});
+
+ ($self->{cat_blob_pid}, $self->{cat_blob_in},
+ $self->{cat_blob_out}, $self->{cat_blob_ctx}) =
+ command_bidi_pipe(qw(cat-file blob --stdin));
+}
+
+sub _close_cat_blob {
+ my ($self) = @_;
+
+ return unless defined($self->{cat_blob_pid});
+
+ my @vars = map { 'cat_blob' . $_ } qw(pid in out ctx);
+
+ command_close_bidi_pipe($self->{@vars});
+ delete $self->{@vars};
+}
=back
@@ -892,7 +981,11 @@ sub _cmd_close {
}
-sub DESTROY { }
+sub DESTROY {
+ my ($self) = @_;
+ $self->_close_hash_and_insert_object();
+ $self->_close_cat_blob();
+}
# Pipe implementation for ActiveState Perl.
--
1.5.3.4.1342.g32de
^ permalink raw reply related
* [PATCH 6/9] git-hash-object: Add --stdin-paths option
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben
In-Reply-To: <1193307927-3592-6-git-send-email-aroben@apple.com>
This allows multiple paths to be specified on stdin.
Signed-off-by: Adam Roben <aroben@apple.com>
---
Documentation/git-hash-object.txt | 5 ++++-
hash-object.c | 29 ++++++++++++++++++++++++++++-
t/t1006-hash-object.sh | 22 ++++++++++++++++++++++
3 files changed, 54 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt
index 616f196..50fc401 100644
--- a/Documentation/git-hash-object.txt
+++ b/Documentation/git-hash-object.txt
@@ -8,7 +8,7 @@ git-hash-object - Compute object ID and optionally creates a blob from a file
SYNOPSIS
--------
-'git-hash-object' [-t <type>] [-w] [--stdin] [--] <file>...
+'git-hash-object' [-t <type>] [-w] [--stdin | --stdin-paths] [--] <file>...
DESCRIPTION
-----------
@@ -32,6 +32,9 @@ OPTIONS
--stdin::
Read the object from standard input instead of from a file.
+--stdin-paths::
+ Read file names from stdin instead of from the command-line.
+
Author
------
Written by Junio C Hamano <junkio@cox.net>
diff --git a/hash-object.c b/hash-object.c
index 18f5017..fd96d50 100644
--- a/hash-object.c
+++ b/hash-object.c
@@ -20,6 +20,7 @@ static void hash_object(const char *path, enum object_type type, int write_objec
? "Unable to add %s to database"
: "Unable to hash %s", path);
printf("%s\n", sha1_to_hex(sha1));
+ maybe_flush_or_die(stdout, "hash to stdout");
}
static void hash_stdin(const char *type, int write_object)
@@ -31,7 +32,7 @@ static void hash_stdin(const char *type, int write_object)
}
static const char hash_object_usage[] =
-"git-hash-object [-t <type>] [-w] [--stdin] <file>...";
+"git-hash-object [-t <type>] [-w] [--stdin | --stdin-paths] <file>...";
int main(int argc, char **argv)
{
@@ -41,6 +42,7 @@ int main(int argc, char **argv)
const char *prefix = NULL;
int prefix_length = -1;
int no_more_flags = 0;
+ int found_stdin_flag = 0;
for (i = 1 ; i < argc; i++) {
if (!no_more_flags && argv[i][0] == '-') {
@@ -62,7 +64,32 @@ int main(int argc, char **argv)
}
else if (!strcmp(argv[i], "--help"))
usage(hash_object_usage);
+ else if (!strcmp(argv[i], "--stdin-paths")) {
+ struct strbuf buf, nbuf;
+
+ if (found_stdin_flag)
+ die("Can't use both --stdin and --stdin-paths");
+ found_stdin_flag = 1;
+
+ strbuf_init(&buf, 0);
+ strbuf_init(&nbuf, 0);
+ while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+ if (buf.buf[0] == '"') {
+ strbuf_reset(&nbuf);
+ if (unquote_c_style(&nbuf, buf.buf, NULL))
+ die("line is badly quoted");
+ strbuf_swap(&buf, &nbuf);
+ }
+ hash_object(buf.buf, type_from_string(type), write_object);
+ }
+ strbuf_release(&buf);
+ strbuf_release(&nbuf);
+ }
else if (!strcmp(argv[i], "--stdin")) {
+ if (found_stdin_flag)
+ die("Can't use both --stdin and --stdin-paths");
+ found_stdin_flag = 1;
+
hash_stdin(type, write_object);
}
else
diff --git a/t/t1006-hash-object.sh b/t/t1006-hash-object.sh
index 12f95f0..e747004 100755
--- a/t/t1006-hash-object.sh
+++ b/t/t1006-hash-object.sh
@@ -24,4 +24,26 @@ test_expect_success \
'hash from stdin and write to database' \
"test $hello_sha1 = \$(echo '$hello_content' | git hash-object -w --stdin)"
+example_content="Silly example"
+example_sha1=f24c74a2e500f5ee1332c86b94199f52b1d1d962
+echo "$example_content" > example
+
+filenames="hello
+example"
+
+sha1s="$hello_sha1
+$example_sha1"
+
+test_expect_success \
+ 'hash two files with names on stdin' \
+ "test '$sha1s' = \"\$(echo '$filenames' | git hash-object --stdin-paths)\""
+
+test_expect_success \
+ 'hash two files with names on stdin and write to database' \
+ "test '$sha1s' = \"\$(echo '$filenames' | git hash-object --stdin-paths)\""
+
+test_expect_failure \
+ "Can't use --stdin and --stdin-paths together" \
+ "echo '$filenames' | git hash-object --stdin --stdin-paths"
+
test_done
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [PATCH 7/9] Git.pm: Add command_bidi_pipe and command_close_bidi_pipe
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben
In-Reply-To: <1193307927-3592-7-git-send-email-aroben@apple.com>
command_bidi_pipe hands back the stdin and stdout file handles from the
executed command. command_close_bidi_pipe closes these handles and terminates
the process.
Signed-off-by: Adam Roben <aroben@apple.com>
---
perl/Git.pm | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 56 insertions(+), 0 deletions(-)
diff --git a/perl/Git.pm b/perl/Git.pm
index 3f4080c..46c5d10 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -51,6 +51,7 @@ require Exporter;
# Methods which can be called as standalone functions as well:
@EXPORT_OK = qw(command command_oneline command_noisy
command_output_pipe command_input_pipe command_close_pipe
+ command_bidi_pipe command_close_bidi_pipe
version exec_path hash_object git_cmd_try);
@@ -92,6 +93,7 @@ increate nonwithstanding).
use Carp qw(carp croak); # but croak is bad - throw instead
use Error qw(:try);
use Cwd qw(abs_path);
+use IPC::Open2 qw(open2);
}
@@ -375,6 +377,60 @@ sub command_close_pipe {
_cmd_close($fh, $ctx);
}
+=item command_bidi_pipe ( COMMAND [, ARGUMENTS... ] )
+
+Execute the given C<COMMAND> in the same way as command_output_pipe()
+does but return both an input pipe filehandle and an output pipe filehandle.
+
+The function will return return C<($pid, $pipe_in, $pipe_out, $ctx)>.
+See C<command_close_bidi_pipe()> for details.
+
+=cut
+
+sub command_bidi_pipe {
+ my ($pid, $in, $out);
+ $pid = open2($in, $out, 'git', @_);
+ return ($pid, $in, $out, join(' ', @_));
+}
+
+=item command_close_bidi_pipe ( PID, PIPE_IN, PIPE_OUT [, CTX] )
+
+Close the C<PIPE_IN> and C<PIPE_OUT> as returned from C<command_bidi_pipe()>,
+checking whether the command finished successfully. The optional C<CTX>
+argument is required if you want to see the command name in the error message,
+and it is the fourth value returned by C<command_bidi_pipe()>. The call idiom
+is:
+
+ my ($pid, $in, $out, $ctx) = $r->command_bidi_pipe('cat-file --stdin');
+ print "000000000\n" $out;
+ while (<$in>) { ... }
+ $r->command_close_bidi_pipe($pid, $in, $out, $ctx);
+
+Note that you should not rely on whatever actually is in C<CTX>;
+currently it is simply the command name but in future the context might
+have more complicated structure.
+
+=cut
+
+sub command_close_bidi_pipe {
+ my ($pid, $in, $out, $ctx) = @_;
+ foreach my $fh ($in, $out) {
+ if (not close $fh) {
+ if ($!) {
+ carp "error closing pipe: $!";
+ } elsif ($? >> 8) {
+ throw Git::Error::Command($ctx, $? >>8);
+ }
+ }
+ }
+
+ waitpid $pid, 0;
+
+ if ($? >> 8) {
+ throw Git::Error::Command($ctx, $? >>8);
+ }
+}
+
=item command_noisy ( COMMAND [, ARGUMENTS... ] )
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [PATCH 5/9] Add tests for git hash-object
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben, Johannes Sixt
In-Reply-To: <1193307927-3592-5-git-send-email-aroben@apple.com>
Signed-off-by: Adam Roben <aroben@apple.com>
---
Johannes Sixt wrote:
> Adam Roben schrieb:
> > +test_expect_success \
> > + 'hash a file' \
> > + "test $hello_sha1 = $(git hash-object hello)"
>
> Put tests in double-quotes; otherwise, the substitutions happen before the test begins, and not as part of the test.
I think escaping the $(...) is enough to delay command execution.
t/t1006-hash-object.sh | 27 +++++++++++++++++++++++++++
1 files changed, 27 insertions(+), 0 deletions(-)
create mode 100755 t/t1006-hash-object.sh
diff --git a/t/t1006-hash-object.sh b/t/t1006-hash-object.sh
new file mode 100755
index 0000000..12f95f0
--- /dev/null
+++ b/t/t1006-hash-object.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+test_description='git hash-object'
+
+. ./test-lib.sh
+
+hello_content="Hello World"
+hello_sha1=557db03de997c86a4a028e1ebd3a1ceb225be238
+echo "$hello_content" > hello
+
+test_expect_success \
+ 'hash a file' \
+ "test $hello_sha1 = \$(git hash-object hello)"
+
+test_expect_success \
+ 'hash from stdin' \
+ "test $hello_sha1 = \$(echo '$hello_content' | git hash-object --stdin)"
+
+test_expect_success \
+ 'hash a file and write to database' \
+ "test $hello_sha1 = \$(git hash-object -w hello)"
+
+test_expect_success \
+ 'hash from stdin and write to database' \
+ "test $hello_sha1 = \$(echo '$hello_content' | git hash-object -w --stdin)"
+
+test_done
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [PATCH 4/9] git-cat-file: Add --stdin option
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben, Brian Downing
In-Reply-To: <1193307927-3592-4-git-send-email-aroben@apple.com>
This lets you specify object names on stdin instead of on the command line.
When printing object contents or pretty-printing, objects will be printed
preceded by their size:
<size>LF
<content>LF
Signed-off-by: Adam Roben <aroben@apple.com>
---
Brian Downing wrote:
> I think a far more reasonable output format for multiple objects would
> be something like:
>
> <count> LF
> <raw data> LF
>
> Where <count> is the number of bytes in the <raw data> as an ASCII
> decimal integer.
Agreed.
Documentation/git-cat-file.txt | 6 ++++-
builtin-cat-file.c | 43 ++++++++++++++++++++++++++++++++++-----
t/t1005-cat-file.sh | 35 ++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 7 deletions(-)
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index afa095c..588d71a 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -8,7 +8,7 @@ git-cat-file - Provide content or type/size information for repository objects
SYNOPSIS
--------
-'git-cat-file' [-t | -s | -e | -p | <type>] <object>
+'git-cat-file' [-t | -s | -e | -p | <type>] [--stdin | <object>]
DESCRIPTION
-----------
@@ -23,6 +23,10 @@ OPTIONS
For a more complete list of ways to spell object names, see
"SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1].
+--stdin::
+ Read object names from stdin instead of specifying one on the
+ command line.
+
-t::
Instead of the content, show the object type identified by
<object>.
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 3a0be4a..ee46ba4 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -76,7 +76,7 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
write_or_die(1, cp, endp - cp);
}
-static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
+static int cat_one_file(int opt, const char *exp_type, const char *obj_name, int print_size)
{
unsigned char sha1[20];
enum object_type type;
@@ -139,16 +139,26 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
if (!buf)
die("git-cat-file %s: bad file", obj_name);
+ if (print_size) {
+ printf("%lu\n", size);
+ fflush(stdout);
+ }
write_or_die(1, buf, size);
+ if (print_size) {
+ printf("\n");
+ fflush(stdout);
+ }
return 0;
}
-static const char cat_file_usage[] = "git-cat-file [-t|-s|-e|-p|<type>] <sha1>";
+static const char cat_file_usage[] = "git-cat-file [-t|-s|-e|-p|<type>] [--stdin | <sha1>]";
int cmd_cat_file(int argc, const char **argv, const char *prefix)
{
- int i, opt = 0;
+ int i, opt = 0, print_size = 0;
+ int read_stdin = 0;
const char *exp_type = 0, *obj_name = 0;
+ struct strbuf buf;
git_config(git_default_config);
@@ -161,6 +171,11 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
continue;
}
+ if (!strcmp(arg, "--stdin")) {
+ read_stdin = 1;
+ continue;
+ }
+
if (arg[0] == '-')
usage(cat_file_usage);
@@ -169,15 +184,31 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
continue;
}
- if (obj_name)
+ if (obj_name || read_stdin)
usage(cat_file_usage);
obj_name = arg;
break;
}
- if (!exp_type || !obj_name)
+ if (!exp_type)
usage(cat_file_usage);
- return cat_one_file(opt, exp_type, obj_name);
+ if (!read_stdin) {
+ if (!obj_name)
+ usage(cat_file_usage);
+ return cat_one_file(opt, exp_type, obj_name, 0);
+ }
+
+ print_size = !opt || opt == 'p';
+
+ strbuf_init(&buf, 0);
+ while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+ int error = cat_one_file(opt, exp_type, buf.buf, print_size);
+ if (error)
+ return error;
+ }
+ strbuf_release(&buf);
+
+ return 0;
}
diff --git a/t/t1005-cat-file.sh b/t/t1005-cat-file.sh
index 697354d..2b2d386 100755
--- a/t/t1005-cat-file.sh
+++ b/t/t1005-cat-file.sh
@@ -88,4 +88,39 @@ test_expect_success \
"Reach a blob from a tag pointing to it" \
"test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""
+sha1s="$hello_sha1
+$tree_sha1
+$commit_sha1
+$tag_sha1"
+
+sizes="$hello_size
+$tree_size
+$commit_size
+$tag_size"
+
+test_expect_success \
+ "Pass object hashes on stdin to retrieve sizes" \
+ "test '$sizes' = \"\$(echo '$sha1s' | git cat-file -s --stdin)\""
+
+example_content="Silly example"
+example_size=$(echo "$example_content" | wc -c)
+example_sha1=f24c74a2e500f5ee1332c86b94199f52b1d1d962
+
+echo "$example_content" > example
+
+git update-index --add example
+
+sha1s="$hello_sha1
+$example_sha1"
+
+contents="$hello_size
+$hello_content
+
+$example_size
+$example_content"
+
+test_expect_success \
+ "Pass object hashes on stdin to retrieve contents" \
+ "test '$contents' = \"\$(echo '$sha1s' | git cat-file blob --stdin)\""
+
test_done
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [PATCH 3/9] git-cat-file: Make option parsing a little more flexible
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben
In-Reply-To: <1193307927-3592-3-git-send-email-aroben@apple.com>
This will make it easier to add newer options later.
Signed-off-by: Adam Roben <aroben@apple.com>
---
builtin-cat-file.c | 42 ++++++++++++++++++++++++++++++------------
1 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 34a63d1..3a0be4a 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -143,23 +143,41 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
return 0;
}
+static const char cat_file_usage[] = "git-cat-file [-t|-s|-e|-p|<type>] <sha1>";
+
int cmd_cat_file(int argc, const char **argv, const char *prefix)
{
- int opt;
- const char *exp_type, *obj_name;
+ int i, opt = 0;
+ const char *exp_type = 0, *obj_name = 0;
git_config(git_default_config);
- if (argc != 3)
- usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");
- exp_type = argv[1];
- obj_name = argv[2];
-
- opt = 0;
- if ( exp_type[0] == '-' ) {
- opt = exp_type[1];
- if ( !opt || exp_type[2] )
- opt = -1; /* Not a single character option */
+
+ for (i = 1; i < argc; ++i) {
+ const char *arg = argv[i];
+
+ if (!strcmp(arg, "-t") || !strcmp(arg, "-s") || !strcmp(arg, "-e") || !strcmp(arg, "-p")) {
+ exp_type = arg;
+ opt = exp_type[1];
+ continue;
+ }
+
+ if (arg[0] == '-')
+ usage(cat_file_usage);
+
+ if (!exp_type) {
+ exp_type = arg;
+ continue;
+ }
+
+ if (obj_name)
+ usage(cat_file_usage);
+
+ obj_name = arg;
+ break;
}
+ if (!exp_type || !obj_name)
+ usage(cat_file_usage);
+
return cat_one_file(opt, exp_type, obj_name);
}
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [PATCH 2/9] git-cat-file: Small refactor of cmd_cat_file
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben
In-Reply-To: <1193307927-3592-2-git-send-email-aroben@apple.com>
I separated the logic of parsing the arguments from the logic of fetching and
outputting the data. cat_one_file now does the latter.
Signed-off-by: Adam Roben <aroben@apple.com>
---
builtin-cat-file.c | 38 ++++++++++++++++++++++----------------
1 files changed, 22 insertions(+), 16 deletions(-)
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index f132d58..34a63d1 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -76,31 +76,16 @@ static void pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
write_or_die(1, cp, endp - cp);
}
-int cmd_cat_file(int argc, const char **argv, const char *prefix)
+static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
{
unsigned char sha1[20];
enum object_type type;
void *buf;
unsigned long size;
- int opt;
- const char *exp_type, *obj_name;
-
- git_config(git_default_config);
- if (argc != 3)
- usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");
- exp_type = argv[1];
- obj_name = argv[2];
if (get_sha1(obj_name, sha1))
die("Not a valid object name %s", obj_name);
- opt = 0;
- if ( exp_type[0] == '-' ) {
- opt = exp_type[1];
- if ( !opt || exp_type[2] )
- opt = -1; /* Not a single character option */
- }
-
buf = NULL;
switch (opt) {
case 't':
@@ -157,3 +142,24 @@ int cmd_cat_file(int argc, const char **argv, const char *prefix)
write_or_die(1, buf, size);
return 0;
}
+
+int cmd_cat_file(int argc, const char **argv, const char *prefix)
+{
+ int opt;
+ const char *exp_type, *obj_name;
+
+ git_config(git_default_config);
+ if (argc != 3)
+ usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");
+ exp_type = argv[1];
+ obj_name = argv[2];
+
+ opt = 0;
+ if ( exp_type[0] == '-' ) {
+ opt = exp_type[1];
+ if ( !opt || exp_type[2] )
+ opt = -1; /* Not a single character option */
+ }
+
+ return cat_one_file(opt, exp_type, obj_name);
+}
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [PATCH 1/9] Add tests for git cat-file
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano, Adam Roben, Johannes Sixt
In-Reply-To: <1193307927-3592-1-git-send-email-aroben@apple.com>
Signed-off-by: Adam Roben <aroben@apple.com>
---
Johannes Sixt wrote:
> Adam Roben schrieb:
> > + test_expect_success \
> > + "$type exists" \
> > + "git cat-file -e $hello_sha1"
>
> You mean $sha1 here, right?
I most definitely did!
> > + test_expect_success \
> > + "Type of $type is correct" \
> > + "test $type = \"$(git cat-file -t $sha1)\""
>
> This should escape the $(...) in all the tests. Like this:
>
> "test $type = \"\$(git cat-file -t $sha1)\""
>
> > +test_expect_success \
> > + "Reach a blob from a tag pointing to it" \
> > + "test \"$hello_content\" = \"$(git cat-file blob $tag_sha1)\""
>
> And use single quotes without escaping the double-quotes here.
Done.
t/t1005-cat-file.sh | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 91 insertions(+), 0 deletions(-)
create mode 100755 t/t1005-cat-file.sh
diff --git a/t/t1005-cat-file.sh b/t/t1005-cat-file.sh
new file mode 100755
index 0000000..697354d
--- /dev/null
+++ b/t/t1005-cat-file.sh
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+test_description='git cat-file'
+
+. ./test-lib.sh
+
+function maybe_remove_timestamp()
+{
+ if test -z "$2"; then
+ echo "$1"
+ else
+ echo "$1" | sed -e 's/ [0-9]\{10\} [+-][0-9]\{4\}$//'
+ fi
+}
+
+function run_tests()
+{
+ type=$1
+ sha1=$2
+ size=$3
+ content=$4
+ pretty_content=$5
+ no_timestamp=$6
+
+ test_expect_success \
+ "$type exists" \
+ "git cat-file -e $sha1"
+ test_expect_success \
+ "Type of $type is correct" \
+ "test $type = \"\$(git cat-file -t $sha1)\""
+ test_expect_success \
+ "Size of $type is correct" \
+ "test $size = \"\$(git cat-file -s $sha1)\""
+ test -z "$content" || test_expect_success \
+ "Content of $type is correct" \
+ "test \"\$(maybe_remove_timestamp '$content' $no_timestamp)\" = \"\$(maybe_remove_timestamp \"\$(git cat-file $type $sha1)\" $no_timestamp)\""
+ test_expect_success \
+ "Pretty content of $type is correct" \
+ "test \"\$(maybe_remove_timestamp '$pretty_content' $no_timestamp)\" = \"\$(maybe_remove_timestamp \"\$(git cat-file -p $sha1)\" $no_timestamp)\""
+}
+
+hello_content="Hello World"
+hello_size=$(echo "$hello_content" | wc -c)
+hello_sha1=557db03de997c86a4a028e1ebd3a1ceb225be238
+
+echo "$hello_content" > hello
+
+git update-index --add hello
+
+run_tests 'blob' $hello_sha1 $hello_size "$hello_content" "$hello_content"
+
+tree_sha1=$(git write-tree)
+tree_size=33
+tree_pretty_content="100644 blob $hello_sha1 hello"
+
+run_tests 'tree' $tree_sha1 $tree_size "" "$tree_pretty_content"
+
+commit_message="Intial commit"
+commit_sha1=$(echo "$commit_message" | git commit-tree $tree_sha1)
+commit_size=177
+commit_content="tree $tree_sha1
+author $GIT_AUTHOR_NAME <$GIT_AUTHOR_EMAIL> 0000000000 +0000
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 0000000000 +0000
+
+$commit_message"
+
+run_tests 'commit' $commit_sha1 $commit_size "$commit_content" "$commit_content" 1
+
+tag_header="object $hello_sha1
+type blob
+tag hellotag
+tagger $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL>"
+tag_description="This is a tag"
+tag_content="$tag_header
+
+$tag_description"
+tag_pretty_content="$tag_header
+Thu Jan 1 00:00:00 1970 +0000
+
+$tag_description"
+
+tag_sha1=$(echo "$tag_content" | git mktag)
+tag_size=$(echo "$tag_content" | wc -c)
+
+run_tests 'tag' $tag_sha1 $tag_size "$tag_content" "$tag_pretty_content"
+
+test_expect_success \
+ "Reach a blob from a tag pointing to it" \
+ "test '$hello_content' = \"\$(git cat-file blob $tag_sha1)\""
+
+test_done
--
1.5.3.4.1337.g8e67d-dirty
^ permalink raw reply related
* [RESEND PATCH 0/9] Make git-svn fetch ~1.7x faster
From: Adam Roben @ 2007-10-25 10:25 UTC (permalink / raw)
To: git; +Cc: Junio Hamano
This is a resend of my previous patch series to speed up git-svn, taking into
account comments from Eric, Johannes, and Brian.
--
Documentation/git-cat-file.txt | 6 +-
Documentation/git-hash-object.txt | 5 +-
builtin-cat-file.c | 87 +++++++++++++++++----
git-svn.perl | 40 +++++-----
hash-object.c | 29 +++++++-
perl/Git.pm | 153 ++++++++++++++++++++++++++++++++++++-
t/t1005-cat-file.sh | 126 ++++++++++++++++++++++++++++++
t/t1006-hash-object.sh | 49 ++++++++++++
8 files changed, 452 insertions(+), 43 deletions(-)
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Andreas Ericsson @ 2007-10-25 10:24 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Peter Baumann, J. Bruce Fields, Steffen Prohaska, Jakub Narebski,
Federico Mena Quintero, git
In-Reply-To: <Pine.LNX.4.64.0710251108330.25221@racer.site>
Johannes Schindelin wrote:
> Hi,
>
> On Thu, 25 Oct 2007, Andreas Ericsson wrote:
>
>> Johannes Schindelin wrote:
>>
>>> On Wed, 24 Oct 2007, Andreas Ericsson wrote:
>>>
>>>> Conceptually, I don't think it'll be any problem what so ever
>>>> telling anyone that the branches that aren't currently checked out
>>>> get merged automatically only if they result in a fast-forward.
>>> It would be a matter of seconds until someone asks "why only
>>> fast-forwards? Would it not be _much_ better to merge _always_?
>>> Stupid git."
>>>
>>> And all because the concept of "local" vs "remote" was blurred.
>> It's already blurred, since we have git-pull instead of just git-fetch.
>
> Huh? How is "I ask git pull to fetch the remote branch, and merge it into
> my local branch" a blurring of local vs remote branch?
>
> The local branch is still the local branch where it is _my_ responsibility
> to update or change anything.
True. So git pull saves you exactly one command. The various fetch-all-git-
repos-and-update-all-fast-forward-branches in circulation at the office
save us ~500 commands each time they're run. Or rather, they *could* do
that, but you can't know until you've run it.
So what should I do to make what I want possible, without having git-pull
muddy the waters of local vs remote? There's clearly a user desire for it,
besides that of my eight co-workers and myself. Introduce git-<cmd-156>?
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Johannes Schindelin @ 2007-10-25 10:17 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Steffen Prohaska, Peter Baumann, J. Bruce Fields, Jakub Narebski,
Federico Mena Quintero, git
In-Reply-To: <47204297.5050109@op5.se>
Hi,
On Thu, 25 Oct 2007, Andreas Ericsson wrote:
> Johannes Schindelin wrote:
>
> > On Thu, 25 Oct 2007, Steffen Prohaska wrote:
> >
> > > On Oct 25, 2007, at 12:14 AM, Johannes Schindelin wrote:
> > >
> > > > But I think I have to drive my message home again: if what you
> > > > desire becomes reality, you take away the clear distinction
> > > > between local and remote branches. In fact, those branches are
> > > > neither local (because the next pull will automatically update
> > > > them with remote changes, but _only_ if they fast-forward) nor
> > > > remote (because you plan to work on them locally).
> > >
> > > Exactly, because I do not work on those branches alone. These are
> > > _shared_ branches. I can work on such a branch with a group of
> > > developers. I'm willing to accept this bit of chaos.
> >
> > It is not just a chaos. I see a serious problem here. On _your_
> > computer, you do _not_ have a shared branch. Which is visible _even_
> > in your modified work flow when you have unpushed changes.
>
> Ofcourse it is. People might pull from it. That's the whole point of a
> distributed model.
By that reasoning, left is right. Because your "left" is my "right".
> > So your desired illusion that your local branches are anything but
> > local branches will never be perfect enough.
> >
> > > Your rebase workflow is not possible if more than one dev wants to
> > > work on the topic branch together.
> >
> > Why not? I do it all the time. CVS users do it all the time, for
> > that matter.
>
> For 200 branches at a time, where any of them might have changed?
I slowly start to understand why your users are confused. _Nobody_ works
on 200 branches at the same time. (No, maintainers don't count: they do
not work _on_ the branches, but _with_; they merge them.)
When you're done with a topic, why do you leave it around? Cluttering up
your "git branch" output?
> > The problem I see here: you know git quite well. Others don't, and
> > will be mightily confused why pull updates local branches sometimes,
> > and sometimes not.
>
> Do you know this, or are you just guessing? I'm getting the exact same
> confusion with the current behaviour. "Why the hell doesn't git update
> all the branches I told the damn stupid tool to auto-merge when I pull?"
That's easy. A merge can have conflicts. Conflicts need a working
directory. You cannot have multiple working directories. (Actually, you
can, with git-new-workdir, which would break down _horribly_ with your
desired change.)
Oh? You don't have local changes? Then why _on earth_ do you have a
local branch?
Ciao,
Dscho
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Johannes Schindelin @ 2007-10-25 10:12 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Peter Baumann, J. Bruce Fields, Steffen Prohaska, Jakub Narebski,
Federico Mena Quintero, git
In-Reply-To: <47204ECA.7040309@op5.se>
Hi,
On Thu, 25 Oct 2007, Andreas Ericsson wrote:
> Johannes Schindelin wrote:
>
> > On Wed, 24 Oct 2007, Andreas Ericsson wrote:
> >
> > > Conceptually, I don't think it'll be any problem what so ever
> > > telling anyone that the branches that aren't currently checked out
> > > get merged automatically only if they result in a fast-forward.
> >
> > It would be a matter of seconds until someone asks "why only
> > fast-forwards? Would it not be _much_ better to merge _always_?
> > Stupid git."
> >
> > And all because the concept of "local" vs "remote" was blurred.
>
> It's already blurred, since we have git-pull instead of just git-fetch.
Huh? How is "I ask git pull to fetch the remote branch, and merge it into
my local branch" a blurring of local vs remote branch?
The local branch is still the local branch where it is _my_ responsibility
to update or change anything. The remote branch is not. If at all, I can
push -- iff it fast-forwards.
The fact that you can set up local mirroring branches (with "git remote
add") which are only updated via "git fetch" is _no_ blurring of the
concepts: we make it quite explicit that you cannot check them out. They
are not local branches.
Hth,
Dscho
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Johannes Schindelin @ 2007-10-25 10:07 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Jakub Narebski, J. Bruce Fields, Steffen Prohaska,
Federico Mena Quintero, git
In-Reply-To: <472048EB.1000707@op5.se>
Hi,
On Thu, 25 Oct 2007, Andreas Ericsson wrote:
> Jakub Narebski wrote:
> > On 10/24/07, Andreas Ericsson <ae@op5.se> wrote:
> >
> > > git pull. Not git push. git pull operates on one working branch at a
> > > time (by default), whereas git push uploads and fast-forwards all
> > > the common branches (by default). I want git pull to work like git
> > > push.
> >
> > git push is opposite (almost) to git fetch, not to git pull.
>
> Not to an end user that has no idea or desire to learn about git remotes
> or anything else.
At some point you _have_ to expect your users to learn something. In the
git documentation, we never pretend that pull is anything else than "fetch
+ merge".
So this assumption of your end user is a lack of training, really.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] git-cvsimport: Add -N option to force a new import
From: Johannes Schindelin @ 2007-10-25 9:56 UTC (permalink / raw)
To: Matt McCutchen; +Cc: Junio C Hamano, git
In-Reply-To: <1193284913.2619.23.camel@mattlaptop2>
Hi,
On Thu, 25 Oct 2007, Matt McCutchen wrote:
> On Wed, 2007-10-24 at 20:17 -0700, Junio C Hamano wrote:
> > Matt McCutchen <matt@mattmccutchen.net> writes:
> >
> > > I had a git repository for development of rsync and wanted to start
> > > importing the upstream CVS with git-cvsimport, but git-cvsimport saw
> > > that the git repository existed and insisted on updating a previous
> > > import. This patch adds an -N option to git-cvsimport to force a new
> > > import and updates the documentation appropriately.
> >
> > Sounds like a useful addition. Tests?
>
> Are there existing tests for git-cvsimport somewhere whose example I
> could follow? (I didn't see any in t/ .) If not, I suppose I will just
> write a simple script that runs git-cvsimport with and without -N and
> with and without an existing, empty git repository and checks that the
> right things happen.
My best bet: t/t9200-cvsexportcommit.sh
Hth,
Dscho
^ permalink raw reply
* Re: Feature request: Limit git-status reports to a directory
From: Johannes Schindelin @ 2007-10-25 9:55 UTC (permalink / raw)
To: Yin Ping; +Cc: Michel Marti, git
In-Reply-To: <46dff0320710241914t7d93aae1t991fbcaacde77046@mail.gmail.com>
Hi,
On Thu, 25 Oct 2007, Yin Ping wrote:
> On 10/25/07, Michel Marti <mma@objectxp.com> wrote:
> > I am sometimes interested in only seeing the status for a specific
> > directory (and its sub-directories), but git-status is no help in this
> > case - passing a directory does some sort of "git-commit --dry-run". I
> > first thought that this is a bug until I saw in the man-page that this
> > is actually a feature...
>
> It's also painful for me. IMHO, the behaviour of "git-status" should
> keep consistent with "git-diff" and "git-log" which allow for the path.
I am not so sure. In other SCMs, "git status" may be a way to do "git
diff --name-only" or "git ls-files", but not in git. Here, it strictly
means "what would be happening if I were to commit _right_ _now_?".
> Another point, It will be helpful to add a config item to change the
> default behaviour for 'git-diff" and "git-log". For example,
> 'diff.defaultcurrentpath=true' to let git only show difference in
> current directory instead of difference in top directory when typing
> 'git-diff'
IMHO it is not asking users too much when you say "git diff ." is for the
current directory, and "git diff" is for the whole working tree.
Besides, we cannot really change the default behaviour, since some
porcelains use "git log" (and certainly there are some which use "git
diff", too). They would suffer from this unexpected -- and indeed
inconsistent, since the setting can differ between repositories -- output.
Hth,
Dscho
^ permalink raw reply
* git-svnimport
From: Felipe Balbi @ 2007-10-25 9:25 UTC (permalink / raw)
To: git
Hello all,
I was importing busybox svn repository to git but I got a connection
timeout after more than 19k commits... is there a way to continue
where the error happened or should I do it all over again ??
Thanks
--
Best Regards,
Felipe Balbi
felipebalbi@users.sourceforge.net
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Steffen Prohaska @ 2007-10-25 8:25 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Peter Baumann, Johannes Schindelin, J. Bruce Fields,
Jakub Narebski, Federico Mena Quintero, git
In-Reply-To: <47204C6D.3020900@op5.se>
On Oct 25, 2007, at 9:57 AM, Andreas Ericsson wrote:
> 50+ repositories, with stable, testing and maint branches. Some
> repos have more
> than that, so it amounts to roughly 200 branches. Each branch can
> be modified by
> anyone (we're a small company - everyone still works everywhere),
> but all changes
> should be done to the tip of the upstream branch. Especially for
> maint this is a
> bit of a problem, since we frequently have consultants out and
> about, and they
> sometimes find a bug that they commit locally to their own repo.
> They're in a
> hurry though, and have no connection to the mothership repo so they
> can't git-pull
> to get up to date. They aren't exactly developers, but savvy enough
> to fix a few
> simple bugs, but the concept of the locally-modifiable branches not
> being updated
> to their remote-tracking counterparts with each git-pull is just
> incomprehensible
> to them. To me, that suggests that we're doing something wrong.
Johannes described a workflow using rebase. It would create
a very clean history avoiding long "parallel roads" and it
mimics what experience git users would probably do: Just work
if you have no connection but cleanup your work by using rebase
before pushing it.
Johannes, and Peter, too, propose to delete local branches
asap to avoid the third copy besides the copy on the server
and the copy in remotes. They suggest that local branches
should be absolutely reserved for local work.
However, my feeling is that the current tools make it too hard
to work the way described. Therefore it's hard to sell such a
workflow to an unexperienced developer. For example checking
out a remote branch for doing some local work, pushing this
work, and cleaning up requires
git checkout -b <branch> origin/<branch>
# work work ...
git push origin <branch>
git checkout <don-t-work-here>
git branch -D <branch>
These are a lot of commands and some of them look quite
redundant. Nearly every command contains <branch>. Why isn't is
sufficient to tell the name of the branch I'm working on once.
And '-D' looks even dangerous to me because it overrides all
safety checks. This should not be needed in daily work.
Here are some questions:
Do you think a workflow using rebase is feasible for
unexperienced git users?
What would be needed to bring such a workflow down to a few,
simple and reliable commands?
I think the general question is what I described in a previous
mail: You have a shared repository containing stable and topic
branches. Provide a workflow that is as simple as possible
for as many as possible developers. The average developer
should need nothing more than equivalents of "cvs update",
"cvs commit" for daily work if there are no conflicts. Note,
there are no redundant branch names allowed in the commands.
If a developer doesn't switch branches there's no need to
tell the branch name. "git pull ; ... ; git push" is simple
but it has the problem of reporting errors that average devs
don't understand.
Steffen
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Andreas Ericsson @ 2007-10-25 8:07 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Peter Baumann, J. Bruce Fields, Steffen Prohaska, Jakub Narebski,
Federico Mena Quintero, git
In-Reply-To: <Pine.LNX.4.64.0710242315310.25221@racer.site>
Johannes Schindelin wrote:
> Hi,
>
> On Wed, 24 Oct 2007, Andreas Ericsson wrote:
>
>> Conceptually, I don't think it'll be any problem what so ever telling
>> anyone that the branches that aren't currently checked out get merged
>> automatically only if they result in a fast-forward.
>
> It would be a matter of seconds until someone asks "why only
> fast-forwards? Would it not be _much_ better to merge _always_? Stupid
> git."
>
> And all because the concept of "local" vs "remote" was blurred.
>
It's already blurred, since we have git-pull instead of just git-fetch.
pull is the dwim version of fetch for anyone who isn't frequently pulling
from multiple repos that aren't configured as remotes (99% of git's users).
It really is. You configure it to merge this and that branch to those and
these branches. Sometimes it does and sometimes it doesn't, and the decision
is based on what branch you're currently on.
Only git-fetch has the clear local vs remote distinction, because it *never*
merges anything.
On a side-note, I'm starting to see why hg has gotten such a user-base.
Their docs focus on one repo per branch, which doesn't have this problem at
all.
So in short, letting "git-pull" fast-forward (or rebase; I like that idea)
the local copies of the remote tracking branches onto those remote tracking
branches will make life easier for:
* People who collaborate with others in a shared environment, where branch
heads frequently change in the mothership repo but all development is
supposed to be done at the tip of those mothership branches anyway.
Nearly all corporate users fall into this category.
* People who just want to track and test the latest and greatest version of
software X. Sometimes trying latest stable, and sometimes going with the
freshest beta. They won't want to do "git merge beta origin/beta" after
having done "git checkout beta", but they sure as hell don't want to run
anything but the latest either. They may contribute once in a while, but
generally just want to make sure they've got the bleeding edge.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Andreas Ericsson @ 2007-10-25 7:57 UTC (permalink / raw)
To: Peter Baumann
Cc: Johannes Schindelin, Steffen Prohaska, J. Bruce Fields,
Jakub Narebski, Federico Mena Quintero, git
In-Reply-To: <20071025073102.GD6069@xp.machine.xx>
Peter Baumann wrote:
> On Thu, Oct 25, 2007 at 09:15:35AM +0200, Andreas Ericsson wrote:
>> Johannes Schindelin wrote:
>>> Hi,
>>> On Thu, 25 Oct 2007, Steffen Prohaska wrote:
>>>> On Oct 25, 2007, at 12:14 AM, Johannes Schindelin wrote:
>>>>
>>>>> But I think I have to drive my message home again: if what you desire
>>>>> becomes reality, you take away the clear distinction between local and
>>>>> remote branches. In fact, those branches are neither local (because the
>>>>> next pull will automatically update them with remote changes, but _only_
>>>>> if they fast-forward) nor remote (because you plan to work on them
>>>>> locally).
>>>> Exactly, because I do not work on those branches alone. These are
>>>> _shared_ branches. I can work on such a branch with a group of
>>>> developers. I'm willing to accept this bit of chaos.
>>> It is not just a chaos. I see a serious problem here. On _your_
>>> computer, you do _not_ have a shared branch. Which is visible _even_ in
>>> your modified work flow when you have unpushed changes.
>> Ofcourse it is. People might pull from it. That's the whole point of a
>> distributed model.
>>
>>> So your desired illusion that your local branches are anything but local
>>> branches will never be perfect enough.
>>>> Your rebase workflow is not possible if more than one dev wants to work
>>>> on the topic branch together.
>>> Why not? I do it all the time. CVS users do it all the time, for that
>>> matter.
>> For 200 branches at a time, where any of them might have changed? Do they
>> *really* go into all those branches and make really, really sure they run
>> git pull before they ever do anything? Isn't there a teensy weensy risk of
>> them forgetting that sometime when they really meant to do it?
>>
>> On the other hand, if they absolutely *must* fork a branch at a specific
>> point in history (rather than "the latest published work this branch has"),
>> won't they run gitk/qgit/git-log/whatever, regardless of where their branch
>> head is?
>>
>>> The problem I see here: you know git quite well. Others don't, and will
>>> be mightily confused why pull updates local branches sometimes, and
>>> sometimes not.
>> Do you know this, or are you just guessing? I'm getting the exact same
>> confusion with the current behaviour. "Why the hell doesn't git update
>> all the branches I told the damn stupid tool to auto-merge when I pull?"
>> frequently echoes around the office. My co-workers aren't interested in
>> learning about git internals, or its reasons for doing what it does.
>> They don't give a damn about local vs remote namespaces for their branches.
>> They want to get some work done the smoothest way possible, but with our
>> small forest of repositories and the bushel of branches in each repo
>> makes life difficult for them, because they just can't imagine that
>> git doesn't do what they told it to, which is "this branch tracks that".
>> They may work on "this", but still want it to track "that" so they don't
>> have to run "git-update-all.sh", or "git-walk-everything.sh" or any other
>> of a dozen small and near-identical scripts floating around the office.
>>
>
> What actually wonders me why you guys do have 200 local branches. I
> usually just create a local branch from the remote IFF I'd like to do some
> work on it. And for inspecting a remote branch, a detached HEAD works just as
> fine ...
>
50+ repositories, with stable, testing and maint branches. Some repos have more
than that, so it amounts to roughly 200 branches. Each branch can be modified by
anyone (we're a small company - everyone still works everywhere), but all changes
should be done to the tip of the upstream branch. Especially for maint this is a
bit of a problem, since we frequently have consultants out and about, and they
sometimes find a bug that they commit locally to their own repo. They're in a
hurry though, and have no connection to the mothership repo so they can't git-pull
to get up to date. They aren't exactly developers, but savvy enough to fix a few
simple bugs, but the concept of the locally-modifiable branches not being updated
to their remote-tracking counterparts with each git-pull is just incomprehensible
to them. To me, that suggests that we're doing something wrong.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Andreas Ericsson @ 2007-10-25 7:42 UTC (permalink / raw)
To: Jakub Narebski
Cc: J. Bruce Fields, Steffen Prohaska, Johannes Schindelin,
Federico Mena Quintero, git
In-Reply-To: <8fe92b430710241648j609d4d00x121836001a69d1e6@mail.gmail.com>
Jakub Narebski wrote:
> On 10/24/07, Andreas Ericsson <ae@op5.se> wrote:
>
>> git pull. Not git push. git pull operates on one working branch
>> at a time (by default), whereas git push uploads and fast-forwards
>> all the common branches (by default). I want git pull to work like
>> git push.
>
> git push is opposite (almost) to git fetch, not to git pull.
>
Not to an end user that has no idea or desire to learn about git remotes
or anything else. They see "ok, push updates all the remote branches, but
only if it's a fast-forward". They also see "righto, git pull updates all
the local branches, and even merges and does other funny things", but they
*don't* understand why git-pull (in their eyes) only update ONE branch that
they can actually check out. From a technical standpoint, fetch and push
are the same, but from the user perspective, push and pull seem much more
alike.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Peter Baumann @ 2007-10-25 7:31 UTC (permalink / raw)
To: Andreas Ericsson
Cc: Johannes Schindelin, Steffen Prohaska, J. Bruce Fields,
Jakub Narebski, Federico Mena Quintero, git
In-Reply-To: <47204297.5050109@op5.se>
On Thu, Oct 25, 2007 at 09:15:35AM +0200, Andreas Ericsson wrote:
> Johannes Schindelin wrote:
>> Hi,
>> On Thu, 25 Oct 2007, Steffen Prohaska wrote:
>>> On Oct 25, 2007, at 12:14 AM, Johannes Schindelin wrote:
>>>
>>>> But I think I have to drive my message home again: if what you desire
>>>> becomes reality, you take away the clear distinction between local and
>>>> remote branches. In fact, those branches are neither local (because the
>>>> next pull will automatically update them with remote changes, but _only_
>>>> if they fast-forward) nor remote (because you plan to work on them
>>>> locally).
>>> Exactly, because I do not work on those branches alone. These are
>>> _shared_ branches. I can work on such a branch with a group of
>>> developers. I'm willing to accept this bit of chaos.
>> It is not just a chaos. I see a serious problem here. On _your_
>> computer, you do _not_ have a shared branch. Which is visible _even_ in
>> your modified work flow when you have unpushed changes.
>
> Ofcourse it is. People might pull from it. That's the whole point of a
> distributed model.
>
>> So your desired illusion that your local branches are anything but local
>> branches will never be perfect enough.
>>> Your rebase workflow is not possible if more than one dev wants to work
>>> on the topic branch together.
>> Why not? I do it all the time. CVS users do it all the time, for that
>> matter.
>
> For 200 branches at a time, where any of them might have changed? Do they
> *really* go into all those branches and make really, really sure they run
> git pull before they ever do anything? Isn't there a teensy weensy risk of
> them forgetting that sometime when they really meant to do it?
>
> On the other hand, if they absolutely *must* fork a branch at a specific
> point in history (rather than "the latest published work this branch has"),
> won't they run gitk/qgit/git-log/whatever, regardless of where their branch
> head is?
>
>> The problem I see here: you know git quite well. Others don't, and will
>> be mightily confused why pull updates local branches sometimes, and
>> sometimes not.
>
> Do you know this, or are you just guessing? I'm getting the exact same
> confusion with the current behaviour. "Why the hell doesn't git update
> all the branches I told the damn stupid tool to auto-merge when I pull?"
> frequently echoes around the office. My co-workers aren't interested in
> learning about git internals, or its reasons for doing what it does.
> They don't give a damn about local vs remote namespaces for their branches.
> They want to get some work done the smoothest way possible, but with our
> small forest of repositories and the bushel of branches in each repo
> makes life difficult for them, because they just can't imagine that
> git doesn't do what they told it to, which is "this branch tracks that".
> They may work on "this", but still want it to track "that" so they don't
> have to run "git-update-all.sh", or "git-walk-everything.sh" or any other
> of a dozen small and near-identical scripts floating around the office.
>
What actually wonders me why you guys do have 200 local branches. I
usually just create a local branch from the remote IFF I'd like to do some
work on it. And for inspecting a remote branch, a detached HEAD works just as
fine ...
-Peter
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Peter Baumann @ 2007-10-25 7:26 UTC (permalink / raw)
To: Andreas Ericsson
Cc: J. Bruce Fields, Steffen Prohaska, Johannes Schindelin,
Jakub Narebski, Federico Mena Quintero, git
In-Reply-To: <471FBF29.8030802@op5.se>
On Wed, Oct 24, 2007 at 11:54:49PM +0200, Andreas Ericsson wrote:
> Peter Baumann wrote:
>> On Wed, Oct 24, 2007 at 11:06:24PM +0200, Andreas Ericsson wrote:
>>> J. Bruce Fields wrote:
>>>> On Wed, Oct 24, 2007 at 10:12:29PM +0200, Steffen Prohaska wrote:
>>>>> On Oct 24, 2007, at 9:48 PM, J. Bruce Fields wrote:
>>>>>
>>>>>>> I want git pull to work like git push.
>>>>>> That strikes me as a less complete solution, since it only helps in
>>>>>> the
>>>>>> case where the other branches all happen to be unmodified locally
>>>>>> (hence
>>>>>> can be fast-forwarded). In other cases the "git push" will still emit
>>>>>> a
>>>>>> spurious error.
>>>>> Well, but then there's something you should really think
>>>>> about.
>>>> Perhaps, but not necessarily; you may have some branches with local
>>>> changes that you're content to leave unpushed (and un-updated).
>>> Sure, but that won't change. The only thing I'm proposing is that
>>> local copies of remote branches are automatically fast-forwarded
>>> on every pull, but only if
>>>
>>> * the branch has no modifications what so ever
>>> * the branch is set up to auto-merge with the particular branch
>>> fetched from the particular remote
>>>
>>> I really don't see any downsides what so ever with this. Those
>>> of you who do, please enlighten me.
>>>
>> You can't check what got added in your pull, e.g you can't review the new
>> code with something like
>> gitk next..origin/next
>
> That's what git-fetch is for.
>
If I run git pull <remote> and have a auto-merge setup, I would merge the
remote side into my local branch. Then doing
gitk ORIG_HEAD..
does the trick for to review what got added _and_ merged into my local
branch. I can't use this for other local branches not checked out. And as
I normally want to merge, your suggested behaviour is fine with me *IFF*
it is configurable _per_ branch.
>> I often do something like this, just to see what got changed. So at least
>> in my opinion you have to add a third point:
>> * the branch has no modifications what so ever
>> * the branch is set up to auto-merge with the particular branch
>> fetched from the particular remote
>> AND
>> * the user set a config option to always autofastfoward if the above
>> conditions are true! This could be implemented as a global option with
>> a per branch overwrite.
>
> I'd be fine with that, except I think it's fairly dangerous to have
> different defaults. The two first points are sort of the core of the
> case I've been arguing all along.
>
I aggree. And thats why I think your autofastforward should be set to
"false" per default, so that the distinction between local and remote
branches would still be clearly defined. Changing this would confuse new
users a lot more, me thinks.
But having the option for power users sounds fine!
>> Only if this option is added so a user can mark a branch to never
>> autofastforward (but it is still possible to have an auto-merge config)
>> you won't
>> loose valuable information.
>
> Sure. I was thinking something along these lines:
>
> [branch "foo"]
> remote = bar
> merge = some-branch
> autofastforward = false
>
Thats exactlcy what I had in mind. Maybe and a
[core]
global_autofastforward = true
so you could have a sane default for every branch which is missing the
autofastforward statement. (or make it per [remote "foo"] ?)
> Or use git-fetch. git-pull is "fetch + merge". Conceptually, I don't
> think it'll be any problem what so ever telling anyone that the branches
> that aren't currently checked out get merged automatically only if they
> result in a fast-forward.
>
I'm not so sure about that.
-Peter
^ permalink raw reply
* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Andreas Ericsson @ 2007-10-25 7:15 UTC (permalink / raw)
To: Johannes Schindelin
Cc: Steffen Prohaska, Peter Baumann, J. Bruce Fields, Jakub Narebski,
Federico Mena Quintero, git
In-Reply-To: <Pine.LNX.4.64.0710250021430.25221@racer.site>
Johannes Schindelin wrote:
> Hi,
>
> On Thu, 25 Oct 2007, Steffen Prohaska wrote:
>
>> On Oct 25, 2007, at 12:14 AM, Johannes Schindelin wrote:
>>
>>> But I think I have to drive my message home again: if what you desire
>>> becomes reality, you take away the clear distinction between local and
>>> remote branches. In fact, those branches are neither local (because
>>> the next pull will automatically update them with remote changes, but
>>> _only_ if they fast-forward) nor remote (because you plan to work on
>>> them locally).
>> Exactly, because I do not work on those branches alone. These are
>> _shared_ branches. I can work on such a branch with a group of
>> developers. I'm willing to accept this bit of chaos.
>
> It is not just a chaos. I see a serious problem here. On _your_
> computer, you do _not_ have a shared branch. Which is visible _even_ in
> your modified work flow when you have unpushed changes.
>
Ofcourse it is. People might pull from it. That's the whole point of a
distributed model.
> So your desired illusion that your local branches are anything but local
> branches will never be perfect enough.
>
>> Your rebase workflow is not possible if more than one dev wants to work
>> on the topic branch together.
>
> Why not? I do it all the time. CVS users do it all the time, for that
> matter.
>
For 200 branches at a time, where any of them might have changed? Do they
*really* go into all those branches and make really, really sure they run
git pull before they ever do anything? Isn't there a teensy weensy risk of
them forgetting that sometime when they really meant to do it?
On the other hand, if they absolutely *must* fork a branch at a specific
point in history (rather than "the latest published work this branch has"),
won't they run gitk/qgit/git-log/whatever, regardless of where their branch
head is?
>
> The problem I see here: you know git quite well. Others don't, and will
> be mightily confused why pull updates local branches sometimes, and
> sometimes not.
Do you know this, or are you just guessing? I'm getting the exact same
confusion with the current behaviour. "Why the hell doesn't git update
all the branches I told the damn stupid tool to auto-merge when I pull?"
frequently echoes around the office. My co-workers aren't interested in
learning about git internals, or its reasons for doing what it does.
They don't give a damn about local vs remote namespaces for their branches.
They want to get some work done the smoothest way possible, but with our
small forest of repositories and the bushel of branches in each repo
makes life difficult for them, because they just can't imagine that
git doesn't do what they told it to, which is "this branch tracks that".
They may work on "this", but still want it to track "that" so they don't
have to run "git-update-all.sh", or "git-walk-everything.sh" or any other
of a dozen small and near-identical scripts floating around the office.
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox