* [PATCH] Implement git remote rename
From: Miklos Vajna @ 2008-11-03 18:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Brandon Casey, git
In-Reply-To: <7v63nh1sc7.fsf@gitster.siamese.dyndns.org>
The new rename subcommand does the followings:
1) Renames the remote.foo configuration section to remote.bar
2) Updates the remote.bar.fetch refspecs
3) Updates the branch.*.remote settings
4) Renames the tracking branches: renames the normal refs and rewrites
the symrefs to point to the new refs.
Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
On Fri, Oct 24, 2008 at 04:33:28PM -0700, Junio C Hamano <gitster@pobox.com> wrote:
> Hmm, remote_get() can read from all three supported places that you
> can define remotes. Could you explain what happens if the old remote
> is read from say $GIT_DIR/remotes/origin and you are renaming it to
> "upstream" with "git remote rename origin upstream"?
Currently it dies because it can't rename config section 'remote.origin'
to 'remote.upstream'.
> I suspect that if you record where you read the configuration from in
> "struct remote" and add necessary code to remove the original when
> rename.old is *not* coming from in-config definition, you would make
> it possible for repositories initialized with older git that has
> either $GIT_DIR/branches/origin or $GIT_DIR/remotes/origin to be
> migrated to the in-config format using "git remote rename origin
> origin".
Yes, that's possible. I think the patch is already large enough that it
would be better to do it as a separate patch, but I like the idea.
One important step is that currently we have to care about the
remote.upstream.fetch variable, but once migration is supported, we have
to pay attention to remote.upstream.url/push as well.
In the meantime here is an updated patch which applies on top of
mv/maint-branch-m-symref. However, it is not meant for 'maint', of
course. :)
The old version did not "rename" (in fact it is not just a rename but it
replaces origin with upstream in the contents) symrefs properly, now the
testcases are extended to check for this, too.
Documentation/git-remote.txt | 6 ++
builtin-remote.c | 153 ++++++++++++++++++++++++++++++++++++++++++
t/t5505-remote.sh | 15 ++++
3 files changed, 174 insertions(+), 0 deletions(-)
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index bb99810..7b227b3 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -11,6 +11,7 @@ SYNOPSIS
[verse]
'git remote' [-v | --verbose]
'git remote add' [-t <branch>] [-m <master>] [-f] [--mirror] <name> <url>
+'git remote rename' <old> <new>
'git remote rm' <name>
'git remote show' [-n] <name>
'git remote prune' [-n | --dry-run] <name>
@@ -61,6 +62,11 @@ only makes sense in bare repositories. If a remote uses mirror
mode, furthermore, `git push` will always behave as if `\--mirror`
was passed.
+'rename'::
+
+Rename the remote named <old> to <new>. All remote tracking branches and
+configuration settings for the remote are updated.
+
'rm'::
Remove the remote named <name>. All remote tracking branches and
diff --git a/builtin-remote.c b/builtin-remote.c
index e396a3a..1ca6cdb 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -10,6 +10,7 @@
static const char * const builtin_remote_usage[] = {
"git remote",
"git remote add <name> <url>",
+ "git remote rename <old> <new>",
"git remote rm <name>",
"git remote show <name>",
"git remote prune <name>",
@@ -329,6 +330,156 @@ static int add_branch_for_removal(const char *refname,
return 0;
}
+struct rename_info {
+ const char *old;
+ const char *new;
+ struct string_list *remote_branches;
+};
+
+static int read_remote_branches(const char *refname,
+ const unsigned char *sha1, int flags, void *cb_data)
+{
+ struct rename_info *rename = cb_data;
+ struct strbuf buf = STRBUF_INIT;
+ struct string_list_item *item;
+ int flag;
+ unsigned char orig_sha1[20];
+ const char *symref;
+
+ strbuf_addf(&buf, "refs/remotes/%s", rename->old);
+ if(!prefixcmp(refname, buf.buf)) {
+ item = string_list_append(xstrdup(refname), rename->remote_branches);
+ symref = resolve_ref(refname, orig_sha1, 1, &flag);
+ if (flag & REF_ISSYMREF)
+ item->util = xstrdup(symref);
+ else
+ item->util = NULL;
+ }
+
+ return 0;
+}
+
+static int mv(int argc, const char **argv)
+{
+ struct option options[] = {
+ OPT_END()
+ };
+ struct remote *oldremote, *newremote;
+ struct strbuf buf = STRBUF_INIT, buf2 = STRBUF_INIT, buf3 = STRBUF_INIT;
+ struct string_list remote_branches = { NULL, 0, 0, 0 };
+ struct rename_info rename;
+ int i;
+
+ if (argc != 3)
+ usage_with_options(builtin_remote_usage, options);
+
+ rename.old = argv[1];
+ rename.new = argv[2];
+ rename.remote_branches = &remote_branches;
+
+ oldremote = remote_get(rename.old);
+ if (!oldremote)
+ die("No such remote: %s", rename.old);
+
+ newremote = remote_get(rename.new);
+ if (newremote && (newremote->url_nr > 1 || newremote->fetch_refspec_nr))
+ die("remote %s already exists.", rename.new);
+
+ strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new);
+ if (!valid_fetch_refspec(buf.buf))
+ die("'%s' is not a valid remote name", rename.new);
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "remote.%s", rename.old);
+ strbuf_addf(&buf2, "remote.%s", rename.new);
+ if (git_config_rename_section(buf.buf, buf2.buf) < 1)
+ return error("Could not rename config section '%s' to '%s'",
+ buf.buf, buf2.buf);
+
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "remote.%s.fetch", rename.new);
+ if (git_config_set_multivar(buf.buf, NULL, NULL, 1))
+ return error("Could not remove config section '%s'", buf.buf);
+ for (i = 0; i < oldremote->fetch_refspec_nr; i++) {
+ char *ptr;
+
+ strbuf_reset(&buf2);
+ strbuf_addstr(&buf2, oldremote->fetch_refspec[i]);
+ ptr = strstr(buf2.buf, rename.old);
+ if (ptr)
+ strbuf_splice(&buf2, ptr-buf2.buf, strlen(rename.old),
+ rename.new, strlen(rename.new));
+ if (git_config_set_multivar(buf.buf, buf2.buf, "^$", 0))
+ return error("Could not append '%s'", buf.buf);
+ }
+
+ read_branches();
+ for (i = 0; i < branch_list.nr; i++) {
+ struct string_list_item *item = branch_list.items + i;
+ struct branch_info *info = item->util;
+ if (info->remote && !strcmp(info->remote, rename.old)) {
+ strbuf_reset(&buf);
+ strbuf_addf(&buf, "branch.%s.remote", item->string);
+ if (git_config_set(buf.buf, rename.new)) {
+ return error("Could not set '%s'", buf.buf);
+ }
+ }
+ }
+
+ /*
+ * First remove symrefs, then rename the rest, finally create
+ * the new symrefs.
+ */
+ for_each_ref(read_remote_branches, &rename);
+ for (i = 0; i < remote_branches.nr; i++) {
+ struct string_list_item *item = remote_branches.items + i;
+ int flag = 0;
+ unsigned char sha1[20];
+ const char *symref;
+
+ symref = resolve_ref(item->string, sha1, 1, &flag);
+ if (!(flag & REF_ISSYMREF))
+ continue;
+ if (delete_ref(item->string, NULL, REF_NODEREF))
+ die("deleting '%s' failed", item->string);
+ }
+ for (i = 0; i < remote_branches.nr; i++) {
+ struct string_list_item *item = remote_branches.items + i;
+
+ if (item->util)
+ continue;
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, item->string);
+ strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
+ rename.new, strlen(rename.new));
+ strbuf_reset(&buf2);
+ strbuf_addf(&buf2, "remote: renamed %s to %s",
+ item->string, buf.buf);
+ if (rename_ref(item->string, buf.buf, buf2.buf))
+ die("renaming '%s' failed", item->string);
+ }
+ for (i = 0; i < remote_branches.nr; i++) {
+ struct string_list_item *item = remote_branches.items + i;
+
+ if (!item->util)
+ continue;
+ strbuf_reset(&buf);
+ strbuf_addstr(&buf, item->string);
+ strbuf_splice(&buf, strlen("refs/remotes/"), strlen(rename.old),
+ rename.new, strlen(rename.new));
+ strbuf_reset(&buf2);
+ strbuf_addstr(&buf2, item->util);
+ strbuf_splice(&buf2, strlen("refs/remotes/"), strlen(rename.old),
+ rename.new, strlen(rename.new));
+ strbuf_reset(&buf3);
+ strbuf_addf(&buf3, "remote: renamed %s to %s",
+ item->string, buf.buf);
+ if (create_symref(buf.buf, buf2.buf, buf3.buf))
+ die("creating '%s' failed", buf.buf);
+ }
+ return 0;
+}
+
static int remove_branches(struct string_list *branches)
{
int i, result = 0;
@@ -695,6 +846,8 @@ int cmd_remote(int argc, const char **argv, const char *prefix)
result = show_all();
else if (!strcmp(argv[0], "add"))
result = add(argc, argv);
+ else if (!strcmp(argv[0], "rename"))
+ result = mv(argc, argv);
else if (!strcmp(argv[0], "rm"))
result = rm(argc, argv);
else if (!strcmp(argv[0], "show"))
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index c4380c7..0c956ba 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -328,4 +328,19 @@ test_expect_success 'reject adding remote with an invalid name' '
'
+# The first three test if the tracking branches are properly renamed,
+# the last two ones check if the config is updated.
+
+test_expect_success 'rename a remote' '
+
+ git clone one four &&
+ (cd four &&
+ git remote rename origin upstream &&
+ rmdir .git/refs/remotes/origin &&
+ test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
+ test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
+ test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
+ test "$(git config branch.master.remote)" = "upstream")
+
+'
test_done
--
1.6.0.2
^ permalink raw reply related
* Re: git bisect v2.6.27 v2.6.26 problem/bug
From: Alejandro Riveira @ 2008-11-03 18:23 UTC (permalink / raw)
To: git
In-Reply-To: <20081103173911.GA12363@xs4all.net>
El Mon, 03 Nov 2008 18:39:15 +0100, Miquel van Smoorenburg escribió:
> I'm trying to nail down a disk statistics issue that was introduced in
> 2.6.27, while 2.6.26 was working OK. So I decided to use git bisect.
>
> However, sometimes I end up with a version before 2.6.26:
>
> $ cat .git/BISECT_LOG
> git-bisect start
> # good: [bce7f793daec3e65ec5c5705d2457b81fe7b5725] Linux 2.6.26
> git-bisect good bce7f793daec3e65ec5c5705d2457b81fe7b5725 # bad:
> [3fa8749e584b55f1180411ab1b51117190bac1e5] Linux 2.6.27 git-bisect bad
> 3fa8749e584b55f1180411ab1b51117190bac1e5 # bad:
> [dd9ca5d9be7eba99d685d733e23d5be7110e9556] USB: usb-serial: fix a sparse
> warning about different signedness git-bisect bad
> dd9ca5d9be7eba99d685d733e23d5be7110e9556 # good:
> [84c3d4aaec3338201b449034beac41635866bddf] Merge commit 'origin/master'
> git-bisect good 84c3d4aaec3338201b449034beac41635866bddf
>
> $ head -4 Makefile
> VERSION = 2
> PATCHLEVEL = 6
> SUBLEVEL = 26
> EXTRAVERSION = -rc8
>
> If at this point I do a 'git bisect good' I end up in a 2.6.26 branch,
> which is good, but after a few bisects I end up at a version before
> v2.6.26 (2.6.26-rc5) again, which should be impossible right ?
Afaik it is not imposible with git you do not get a linear history
>
> Anyway - at the end I end up with a 'good' version that is
> 2.6.26-rc<something> which is kind of useless. I know that version up to
> 2.6.26 are good ...
>
> What am I doing wrong ?
>
> (git version 1.5.6.5 from debian/lenny)
>
> Mike.
^ permalink raw reply
* Re: [PATCH] Make Pthread link flags configurable
From: David Syzdek @ 2008-11-03 18:18 UTC (permalink / raw)
To: Jakub Narebski; +Cc: David M. Syzdek, git
In-Reply-To: <m3hc6pf8k6.fsf@localhost.localdomain>
On Mon, Nov 3, 2008 at 12:44 AM, Jakub Narebski <jnareb@gmail.com> wrote:
> david.syzdek@acsalaska.net writes:
>
>> From: David M. Syzdek <david.syzdek@acsalaska.net>
>>
>> FreeBSD 4.x systems use the linker flags `-pthread' instead of the
>> linker flags `-lpthread' when linking against the pthread library.
>>
>> Signed-off-by: David M. Syzdek <david.syzdek@acsalaska.net>
>> ---
>> Makefile | 4 +++-
>> 1 files changed, 3 insertions(+), 1 deletions(-)
>
> Would it be possible to add support for this also to configure.ac
> (and config.mak.in)?
>
I just sent a patch to the list that adds autoconf tests for pthreads.
If the test is able to determine which flag to use, then it also sets
THREADED_DELTA_SEARCH.
^ permalink raw reply
* [PATCH] Add autoconf tests for pthreads
From: david.syzdek @ 2008-11-03 18:14 UTC (permalink / raw)
To: git; +Cc: jnareb, David M. Syzdek
From: David M. Syzdek <david.syzdek@acsalaska.net>
Sets the value of PTHREAD_LIBS to the correct flags for linking pthreads on
the current environment. If the correct flags can be determined then
THREADED_DELTA_SEARCH is set. If the correct flags cannot be determined,
then THREADED_DELTA_SEARCH is unset.
Signed-off-by: David M. Syzdek <david.syzdek@acsalaska.net>
---
config.mak.in | 2 ++
configure.ac | 20 ++++++++++++++++++++
2 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/config.mak.in b/config.mak.in
index 7170729..3d3fbcd 100644
--- a/config.mak.in
+++ b/config.mak.in
@@ -51,3 +51,5 @@ OLD_ICONV=@OLD_ICONV@
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
FREAD_READS_DIRECTORIES=@FREAD_READS_DIRECTORIES@
SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
+THREADED_DELTA_SEARCH=@THREADED_DELTA_SEARCH@
+PTHREAD_LIBS=@PTHREAD_LIBS@
diff --git a/configure.ac b/configure.ac
index 9dfc0d3..3bf5d15 100644
--- a/configure.ac
+++ b/configure.ac
@@ -489,6 +489,26 @@ AC_SUBST(NO_MKDTEMP)
#
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
# Enable it on Windows. By default, symrefs are still used.
+#
+# Define PTHREAD_LIBS to the linker flag used for Pthread support and define
+# THREADED_DELTA_SEARCH if Pthreads are available.
+AC_LANG_CONFTEST([AC_LANG_PROGRAM(
+ [[#include <pthread.h>]],
+ [[pthread_mutex_t test_mutex;]]
+)])
+${CC} -pthread conftest.c -o conftest.o > /dev/null 2>&1
+if test $? -eq 0;then
+ PTHREAD_LIBS="-pthread"
+ THREADED_DELTA_SEARCH=YesPlease
+else
+ ${CC} -lpthread conftest.c -o conftest.o > /dev/null 2>&1
+ if test $? -eq 0;then
+ PTHREAD_LIBS="-lpthread"
+ THREADED_DELTA_SEARCH=YesPlease
+ fi
+fi
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(THREADED_DELTA_SEARCH)
## Site configuration (override autodetection)
## --with-PACKAGE[=ARG] and --without-PACKAGE
--
1.6.0.2.GIT
^ permalink raw reply related
* git bisect v2.6.27 v2.6.26 problem/bug
From: Miquel van Smoorenburg @ 2008-11-03 17:39 UTC (permalink / raw)
To: git; +Cc: mikevs
I'm trying to nail down a disk statistics issue that was introduced
in 2.6.27, while 2.6.26 was working OK. So I decided to use git bisect.
However, sometimes I end up with a version before 2.6.26:
$ cat .git/BISECT_LOG
git-bisect start
# good: [bce7f793daec3e65ec5c5705d2457b81fe7b5725] Linux 2.6.26
git-bisect good bce7f793daec3e65ec5c5705d2457b81fe7b5725
# bad: [3fa8749e584b55f1180411ab1b51117190bac1e5] Linux 2.6.27
git-bisect bad 3fa8749e584b55f1180411ab1b51117190bac1e5
# bad: [dd9ca5d9be7eba99d685d733e23d5be7110e9556] USB: usb-serial: fix a sparse warning about different signedness
git-bisect bad dd9ca5d9be7eba99d685d733e23d5be7110e9556
# good: [84c3d4aaec3338201b449034beac41635866bddf] Merge commit 'origin/master'
git-bisect good 84c3d4aaec3338201b449034beac41635866bddf
$ head -4 Makefile
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 26
EXTRAVERSION = -rc8
If at this point I do a 'git bisect good' I end up in a 2.6.26
branch, which is good, but after a few bisects I end up at
a version before v2.6.26 (2.6.26-rc5) again, which should be
impossible right ?
Anyway - at the end I end up with a 'good' version that is
2.6.26-rc<something> which is kind of useless. I know that
version up to 2.6.26 are good ...
What am I doing wrong ?
(git version 1.5.6.5 from debian/lenny)
Mike.
^ permalink raw reply
* Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.
From: Francis Galiegue @ 2008-11-03 17:45 UTC (permalink / raw)
To: Alexander Gavrilov; +Cc: git
In-Reply-To: <bb6f213e0811030926n32c1befcj5d9add6378f7dce4@mail.gmail.com>
Le Monday 03 November 2008 18:26:44 Alexander Gavrilov, vous avez écrit :
> On Mon, Nov 3, 2008 at 7:54 PM, Francis Galiegue <fg@one2team.net> wrote:
> > It just seems to me that this is emulating functionality that multiple Web servers already provide...
> >
> > What's more, knowledge about these Web servers are _much_ more widespread than knowledge about gitweb.
> >
> > Why reinvent the wheel?
>
> If you are speaking of web servers as in 'GitHub', then it is
> irrelevant, because its server software is nonfree.
>
I didn't even account for these.
> If you are speaking of web servers as in 'Apache', then how would it
> know which files are going to be accessed when it executes
> cgi-bin/gitweb.cgi?p=very/private/project.git to check permissions?
>
Well, as far as Apache is concerned, it can do:
* basic .htpasswd authentication,
* LDAP,
* PAM,
* SSL certificate check (via mod_ssl),
* probably others.
Plenty of possibilities.
Well, that's just mho. But if ever I complete my current work on
git-cvsimport (or using git2(svn|git)), I'll go for option 2: my LDAP
database has all the info, and Apache knows about Cache-Control, not
gitweb...
NOTE: I'm just saying here that your patch is of no use as far as _I_
am concerned. I'm basically saying that git cannot account for all
authentication schemes out there. Neither can Apache, but it supports a
buckload of them already.
--
fge
^ permalink raw reply
* Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.
From: Alexander Gavrilov @ 2008-11-03 17:26 UTC (permalink / raw)
To: Francis Galiegue; +Cc: git
In-Reply-To: <200811031754.00545.fg@one2team.net>
On Mon, Nov 3, 2008 at 7:54 PM, Francis Galiegue <fg@one2team.net> wrote:
> It just seems to me that this is emulating functionality that multiple Web servers already provide...
>
> What's more, knowledge about these Web servers are _much_ more widespread than knowledge about gitweb.
>
> Why reinvent the wheel?
If you are speaking of web servers as in 'GitHub', then it is
irrelevant, because its server software is nonfree.
If you are speaking of web servers as in 'Apache', then how would it
know which files are going to be accessed when it executes
cgi-bin/gitweb.cgi?p=very/private/project.git to check permissions?
Alexander
^ permalink raw reply
* Re: [RFC PATCH] gitweb: Support filtering projects by .htaccess files.
From: Francis Galiegue @ 2008-11-03 16:54 UTC (permalink / raw)
To: Alexander Gavrilov; +Cc: git
In-Reply-To: <200811031943.30033.angavrilov@gmail.com>
Le Monday 03 November 2008 17:43:29, vous avez écrit :
> Some environments may require selective limiting of read access to
> repositories. While even dumb http transport supports it through .htaccess
> files, gitweb currently does not implement discretionary access control.
>
> This patch adds a configuration-contolled check that matches simple
> 'Reguire user'/'Reguire group' lines in the .htaccess files with the
> authenticated user name. Using group authentication requires specifying
> a path to the Apache group file in the configuration.
>
> Using htaccess has an additional bonus that the same authentication
> data can be used both for gitweb and the dumb http transport.
>
> Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
It just seems to me that this is emulating functionality that multiple Web servers already provide...
What's more, knowledge about these Web servers are _much_ more widespread than knowledge about gitweb.
Why reinvent the wheel?
Just a thought,
--
fge
^ permalink raw reply
* Re: CRLF support bugs (was: Re: .gitattributes glob matching broken)
From: Dmitry Potapov @ 2008-11-03 16:46 UTC (permalink / raw)
To: Hannu Koivisto; +Cc: git, Jeff King
In-Reply-To: <83y700alzf.fsf_-_@kalahari.s2.org>
On Mon, Nov 03, 2008 at 05:05:24PM +0200, Hannu Koivisto wrote:
>
> Actually, even if .gitattributes were applied in checkout, I think
> the whole CRLF support is broken by design because people will have
> to remember to use -n in clone, then enable core.autocrlf support
> and then checkout. This makes it unneccessarily complicated to
> create "quick local clones" as well. You might suggest that
> Windows users should enable core.autocrlf globally but it may not
> be the right thing to do for all projects/repositories either.
core.autocrlf was exactly meant to be set globally. Basically,
it says what end-of-line should be on your system. It is strange
to have it different for different repositories.
>
> I think CRLF conversion support should have some attribute (be it
> .gitattributes attribute or something else) that is somehow
> inherited from the parent repository. It would basically say that
> "you should use platform's native line end type for text files with
> this repository and its children".
It is already so. All text files are treated accordingly to users
preferences, and for those files where automatic heuristic produces
undesirable result, it can be disabled using .gitattributes. (Alas,
there is a bug with checkout that you encountered earlier).
> To go with that, one would
> maybe have a configuration option to tell what that platform
> default line end type is (just in case someone wants to pretend
> Cygwin is Unix or something like that).
That is exactly what core.autocrlf is about. One user may want to
have LF on Windows and another wants CRLF. So, core.autocrlf defines
how text files should be treated. It is what each user may have in
his/her own ~/.gitconfig.
>
> I also observed this problem:
>
> # Pretend someone does this on Unix
> mkdir test1
> cd test1
> git init
> echo "*.c crlf" > .gitattributes
> echo -en "foo\r\nfoo\r\nfoo\r\n" > kala.c
The 'crlf' attribute means that the file should be treated as 'text'
without applying heuristic. The correct ending for text files on Unix
is '\n', not '\r\n'. So, you put a text file with incorrect ending,
not surprisingly it causes problems for Windows users later.
Dmitry
^ permalink raw reply
* [RFC PATCH] gitweb: Support filtering projects by .htaccess files.
From: Alexander Gavrilov @ 2008-11-03 16:43 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski, Petr Baudis, Giuseppe Bilotta
Some environments may require selective limiting of read access to
repositories. While even dumb http transport supports it through .htaccess
files, gitweb currently does not implement discretionary access control.
This patch adds a configuration-contolled check that matches simple
'Reguire user'/'Reguire group' lines in the .htaccess files with the
authenticated user name. Using group authentication requires specifying
a path to the Apache group file in the configuration.
Using htaccess has an additional bonus that the same authentication
data can be used both for gitweb and the dumb http transport.
Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com>
---
I also created a gitosis fork that can generate the necessary files:
http://repo.or.cz/w/gitosis/httpauth.git
-- Alexander
gitweb/INSTALL | 14 ++++++++++
gitweb/gitweb.perl | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 79 insertions(+), 3 deletions(-)
diff --git a/gitweb/INSTALL b/gitweb/INSTALL
index 26967e2..0841db6 100644
--- a/gitweb/INSTALL
+++ b/gitweb/INSTALL
@@ -166,6 +166,20 @@ Gitweb repositories
shows repositories only if this file exists in its object database
(if directory has the magic file named $export_ok).
+- Finally, it is possible to use primitive .htaccess authentication by
+ enabling the $check_htaccess variable in the config file. Gitweb
+ recognizes the following htaccess commands:
+
+ Require user name1 name2 ... # grant access to the listed users
+ Require group group1 group2 ... # grant access to the listed groups
+ Deny from all # deny unless overridden by a Require
+
+ Access is granted if the currently authenticated user matches one
+ of the Require lines, or if the file does not contain any of the listed
+ commands, or if .htaccess does not exist. If the file exists but cannot
+ be opened, access is denied. To use group authentication you have to
+ point $auth_group_file to the group list in Apache format.
+
Generating projects list using gitweb
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 63c793e..4b962c3 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -98,6 +98,12 @@ our $export_ok = "++GITWEB_EXPORT_OK++";
# only allow viewing of repositories also shown on the overview page
our $strict_export = "++GITWEB_STRICT_EXPORT++";
+# check basic authentication rules in .htaccess
+our $check_htaccess = 0;
+
+# name of the file that lists groups for htaccess check
+our $auth_group_file = "";
+
# list of git base URLs used for URL to where fetch project from,
# i.e. full URL is "$git_base_url/$project"
our @git_base_url_list = grep { $_ ne '' } ("++GITWEB_BASE_URL++");
@@ -397,10 +403,64 @@ sub check_head_link {
(-l $headfile && readlink($headfile) =~ /^refs\/heads\//));
}
+# set of htaccess groups for the current user
+our %cur_auth_groups = ();
+
+sub find_current_groups($$) {
+ my ($gfile, $user) = @_;
+ return () unless $gfile && $user;
+
+ my @groups;
+ open my $gf, $gfile or return ();
+
+ while(<$gf>) {
+ next unless /^\s*(\S+)\s*:\s*(\S.*\S)\s*$/;
+ my ($grp, $usrs) = ($1, $2);
+ push @groups, $grp if grep { $_ eq $user } split (' ', $usrs);
+ }
+
+ close $gf;
+ return @groups;
+}
+
+sub check_htaccess_files($) {
+ my ($dir) = @_;
+ my $user = $cgi->remote_user() || ' ';
+
+ while (length $dir >= length $projectroot) {
+ my $file = "$dir/.htaccess";
+ next unless -e $file;
+ open my $htf, $file or return 0;
+
+ my $ok = 0;
+ my $need_ok = 0;
+ while (<$htf>) {
+ if (/^\s*Require\s+user\s+(\S.*\S)\s*$/i) {
+ $ok++ if grep { $_ eq $user; } split (' ', $1);
+ $need_ok++;
+ } elsif (/^\s*Require\s+group\s+(\S.*\S)\s*$/i) {
+ $ok++ if grep { $cur_auth_groups{$_}; } split(' ', $1);
+ $need_ok++;
+ } elsif (/^\s*Deny\s+from\s+all\s*$/ix) {
+ $need_ok++;
+ }
+ }
+ close $htf;
+
+ return $ok if $need_ok;
+ last;
+ } continue {
+ $dir =~ s/\/[^\/]*$// or last;
+ }
+
+ return 1;
+}
+
sub check_export_ok {
my ($dir) = @_;
return (check_head_link($dir) &&
- (!$export_ok || -e "$dir/$export_ok"));
+ (!$export_ok || -e "$dir/$export_ok") &&
+ (!$check_htaccess || check_htaccess_files($dir)));
}
# process alternate names for backward compatibility
@@ -626,6 +686,9 @@ if (defined $action) {
}
}
+# compute authenticated groups
+$cur_auth_groups{$_}++ for find_current_groups($auth_group_file, $cgi->remote_user());
+
# parameters which are pathnames
our $project = $input_params{'project'};
if (defined $project) {
@@ -853,8 +916,7 @@ sub validate_project {
my $input = shift || return undef;
if (!validate_pathname($input) ||
!(-d "$projectroot/$input") ||
- !check_head_link("$projectroot/$input") ||
- ($export_ok && !(-e "$projectroot/$input/$export_ok")) ||
+ !check_export_ok("$projectroot/$input") ||
($strict_export && !project_in_list($input))) {
return undef;
} else {
--
1.6.0.3.15.gb8d36
^ permalink raw reply related
* Re: [PATCH] Avoid using non-portable `echo -n` in tests.
From: Mike Ralphson @ 2008-11-03 16:30 UTC (permalink / raw)
To: Jeff King; +Cc: Brian Gernhardt, Git List, Shawn O Pearce
In-Reply-To: <20081031182456.GC3230@sigill.intra.peff.net>
2008/10/31 Jeff King <peff@peff.net>:
> On Fri, Oct 31, 2008 at 01:09:13AM -0400, Brian Gernhardt wrote:
>
>> Not all /bin/sh have a builtin echo that recognizes -n. Using printf
>> is far more portable.
>>
>> Discovered on OS X 10.5.5 in t4030-diff-textconv.sh and changed in all
>> the test scripts.
>
> Hmph. I think this is a good patch, and there is precedent in the past
> (20fa04ea, 2aad957, 9754563). But I am surprised this was not caught by
> our recent autobuilding project.
>
> However, it seems to work on FreeBSD (which makes it doubly weird that
> it is broken on OS X). On Solaris, the /bin/sh is so horribly broken
> that I have to use bash anyway. Commit 9754563 claims breakage on AIX,
> but it looks like Mike is doing the AIX builds with bash.
I've just retested with AIX's standard sh (ksh) instead of bash and
there were only two issues.
Oddly enough, one was with the (original) printfs in
t4030-diff-textconv.sh. AIX seems to ship with a perfectly good
printf, but if you install the GNU tools from the 'IBM toolbox for
AIX' (and prepend them to your PATH) it replaces that printf with one
which doesn't grok the "\\1\\n" syntax, but I think wants it to be
"\\01\\n".
The other problem is the 'trap exit' one discussed here:
http://thread.gmane.org/gmane.comp.version-control.git/92748/focus=92944
Mike
^ permalink raw reply
* Re: libgit2 - a true git library
From: Shawn O. Pearce @ 2008-11-03 16:20 UTC (permalink / raw)
To: David Brown; +Cc: Scott Chacon, Nicolas Pitre, Pierre Habouzit, david, git
In-Reply-To: <20081102050917.GA26634@linode.davidb.org>
David Brown <git@davidb.org> wrote:
> On Sat, Nov 01, 2008 at 06:07:04PM -0700, Scott Chacon wrote:
>
>> Think about trying to incorporate this into something proprietary,
>> Shawn - how much of a pain is it going to be to get that license
>> reviewed in Google? However, LGPL I'm sure there is already a
>> reviewed policy. Now, since that may be a pain, time that Shawn could
>> have been spending being paid to work on the library is lost because
>> they can't use it, or it takes weeks/months to review it. That's my
>> concern.
>
> The gcc exception license should have been reviewed by anyone who has
> ever build anything proprietary out of gcc.
Indeed. And gcc is a *very* popular compiler on Linux distributions.
A lot of commerical software is built under it, and distributed in
binary-only form. Those companies have already done the legal review
they felt necessary before shipping (and selling) that software.
--
Shawn.
^ permalink raw reply
* Re: error: packfile while git fsck
From: Nicolas Ferre @ 2008-11-03 16:18 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: git
In-Reply-To: <alpine.LFD.2.00.0810221323270.26244@xanadu.home>
Nicolas Pitre :
> On Wed, 22 Oct 2008, Nicolas Ferre wrote:
>
>> Nicolas Pitre :
>>> On Wed, 22 Oct 2008, Nicolas Ferre wrote:
>>>
>>>> Hi all,
>>>> (please cc me on response)
>>>>
>>>> I am facing error during git status & git fsck on my tree.
>>>> This tree is cloned from various linux kernel trees.
>>>>
>>>> Here are a sample of the error I see :
>>>>
>>>> $ git fsck
>>>> error: packfile
>>>> .git/objects/pack/pack-2ab31ad1f8cb69d091a56fe936634e4796606d49.pack does
>>>> not
>>>> match index
>>>> error: packfile
>>>> .git/objects/pack/pack-2ab31ad1f8cb69d091a56fe936634e4796606d49.pack
>>>> cannot be
>>>> accessed
>>> [...]
>>>
>>> What git version?
>> $ git --version
>> git version 1.5.3.7
>
> OK. Since this is not bleeding edge, it is pretty unlikely that the
> corruption is due to git itself. Furthermore, the git packs are always
> read only once they've been created, meaning that if they weren't
> corrupted at some point then something outside of git caused the
> corruption. You really should consider the possible causes for that
> (dying disk, pilot error, etc).
>
> As to recovery... That really depends if you have personal work
> committed to your repository. If not then the easiest solution is
> simply to recreate it by refetching from upstream. If you have
> personal work in there then you could try to fetch your work branch into
> the newly created repository. The latest git version could help with
> the extraction of non-corrupted objects out of a bad pack, but if the
> objects you are interested in are themselves corrupted then your only
> hope is to have a copy of those objects somewhere else.
Nicolas,
Thanks for your help. I will consider migrating to a brand new git tree
with my work imported in (it seems that my local work is not affected).
Just to know, as the object I try to access is not present, is there a
way to rebuild the index to match this mater of fact ?
Regards,
--
Nicolas Ferre
^ permalink raw reply
* Re: [PATCH 3/3] pack-objects: honor '.keep' files
From: Shawn O. Pearce @ 2008-11-03 16:17 UTC (permalink / raw)
To: drafnel; +Cc: git, gitster, nico
In-Reply-To: <4002818.1225643406819.JavaMail.teamon@b303.teamon.com>
drafnel@gmail.com wrote:
> From: Brandon Casey <drafnel@gmail.com>
>
> By default, pack-objects creates a pack file with every object specified by
> the user. There are two options which can be used to exclude objects which
> are accessible by the repository.
>
> 1) --incremental
> This excludes any object which already exists in an accessible pack.
>
> 2) --local
> This excludes any object which exists in a non-local pack.
>
> With this patch, both arguments also cause objects which exist in packs
> marked with a .keep file to be excluded. Only the --local option requires
> an explicit check for the .keep file. If the user doesn't want the objects
> in a pack marked with .keep to be exclude, then the .keep file should be
> removed.
>
> Additionally, this fixes the repack bug which allowed porcelain repack to
> create packs which contained objects already contained in existing packs
> marked with a .keep file.
This looks sane to me, but I'm holding off on the ack because
I don't like the way the flags are managed in struct packed_git.
(See my reply to 1/3 in the series.)
> Signed-off-by: Brandon Casey <drafnel@gmail.com>
> ---
>
>
> This seems to be the correct fix.
>
> I thought about two alternatives:
>
> 1) New option to pack-objects which causes it to honor .keep files
>
> I didn't think this was necessary since that is why we have .keep
> files in the first place.
>
> So, now there are three variants:
>
> Neither --incremental or --local is used)
> Ignore repo packs, pack is created using all objects specified by
> user.
> --incremental is used)
> Look at repo packs, exclude already packed objects (including those
> marked with .keep file)
> --local is used)
> Look at repo packs, exclude objects in non-local packs (including local
> objects marked with .keep file)
>
> 2) Always honor .keep files, even when --incremental or --local is
> not specified.
>
> I think this may be counter-intuitive, since if you specify all of
> the objects explicitly, without using any other options, you expect
> all of those objects to be placed into the created pack file. If
> .keep is always honored, then a new option would be required to
> indicate ignoring .keep files, or we would adopt the platform that
> "the user must just remove the .keep file".
>
>
> So, honoring .keep files only with --incremental (which is a side effect) or
> --local seems to be the most appropriate.
>
> Comments welcome.
>
> -brandon
>
>
> builtin-pack-objects.c | 2 +-
> t/t7700-repack.sh | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
> index 6a8b9bf..5199e54 100644
> --- a/builtin-pack-objects.c
> +++ b/builtin-pack-objects.c
> @@ -701,7 +701,7 @@ static int add_object_entry(const unsigned char *sha1, enum object_type type,
> break;
> if (incremental)
> return 0;
> - if (local && !ispacklocal(p))
> + if (local && (!ispacklocal(p) || haspackkeep(p)))
> return 0;
> }
> }
> diff --git a/t/t7700-repack.sh b/t/t7700-repack.sh
> index 1489e68..b6b02da 100755
> --- a/t/t7700-repack.sh
> +++ b/t/t7700-repack.sh
> @@ -4,7 +4,7 @@ test_description='git repack works correctly'
>
> . ./test-lib.sh
>
> -test_expect_failure 'objects in packs marked .keep are not repacked' '
> +test_expect_success 'objects in packs marked .keep are not repacked' '
> echo content1 > file1 &&
> echo content2 > file2 &&
> git add . &&
> --
> 1.6.0.2.588.g3102
>
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Shawn.
^ permalink raw reply
* Re: [PATCH 1/3] packed_git: convert pack_local flag into generic bit mask
From: Shawn O. Pearce @ 2008-11-03 16:12 UTC (permalink / raw)
To: drafnel; +Cc: git, gitster, nico
In-Reply-To: <6141358.1225643400587.JavaMail.teamon@b303.teamon.com>
drafnel@gmail.com wrote:
> This is in preparation for adding a flag indicating whether a .keep file is
> present.
Good idea.
> diff --git a/cache.h b/cache.h
> index b0edbf9..0cb9350 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -679,12 +679,15 @@ extern struct packed_git {
> int index_version;
> time_t mtime;
> int pack_fd;
> - int pack_local;
> + unsigned int flags;
Hmm, isn't this a smaller change to make?
- int pack_local;
+ unsigned pack_local:1;
Then later you can do:
- unsigned pack_local:1;
+ unsigned pack_local:1,
+ pack_keep:1;
and the compiler handles all the bitmask stuff for you?
In general in git.git we like to use the struct bitmask stuff when
possible as the code is easier to follow. We only use explicit
mask constants and mask operations when the data is being stored
on disk or written over the network and we need to ensure it is
consistent across compilers. But for in-core only stuff, struct
bitmasks are easier.
--
Shawn.
^ permalink raw reply
* Re: [Q] Abbreviated history graph?
From: Santi Béjar @ 2008-11-03 16:08 UTC (permalink / raw)
To: Brian Foster; +Cc: Git Mailing List
In-Reply-To: <200811031646.20404.brian.foster@innova-card.com>
On Mon, Nov 3, 2008 at 4:46 PM, Brian Foster
<brian.foster@innova-card.com> wrote:
> On Monday 03 November 2008 15:20:30 Santi Béjar wrote:
>>[ ... ]
>> > Is there some way of doing something similar [ the example ]
>> > (git v1.6.0.2)? In addition to 'gitk', we also (rather
>> > quickly!) tried both 'qgit' and 'giggle', but without
>> > any apparent success.
>>
>> Not in git.git but you can use the script at the bottom [ ... ].
>
> Santi,
>
> Thanks. Unfortunately, neither I nor my colleague can try
> it at the moment: It uses `git log --pretty=format:%d'
> which is very new (added c.9-Sept) and not in the versions
> of git we are currently using. End result is the tempfile
> is always empty, and hence `gitk' shows everything.
Ups! So you could get the same information with the uglier (and slower):
$ git log --reverse --pretty=short --decorate | grep ^commit
but then you should change "NF>=2" with "NF>=3", or use an older one I
sent to the list (search for git-overview).
Santi
^ permalink raw reply
* [PATCH - RESEND] git-cvsimport.perl: use humand readable names for options
From: Francis Galiegue @ 2008-11-03 16:00 UTC (permalink / raw)
To: git
It's not really because I've had a lack of comments :p, but because the previous patch I sent had a leftover variable that was useless in read_repo_config(). Fixed in this one.
Still welcoming comments as to option variable names, though.
----
git-cvsimport.perl: use humand readable names for options
This has required to use Getopt::Long another way, and a rewrite of the
read_repo_config() sub. The good thing with the latter is that "no strict
'refs';" has now disappeared.
---
git-cvsimport.perl | 242 ++++++++++++++++++++++++++++++++--------------------
1 files changed, 148 insertions(+), 94 deletions(-)
diff --git a/git-cvsimport.perl b/git-cvsimport.perl
index e439202..94b183a 100755
--- a/git-cvsimport.perl
+++ b/git-cvsimport.perl
@@ -29,7 +29,51 @@ use IPC::Open2;
$SIG{'PIPE'}="IGNORE";
$ENV{'TZ'}="UTC";
-our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_L, $opt_a, $opt_r);
+#
+# Option values
+#
+my $help = undef; # -h
+my $branch_for_head = undef; # -o
+my $verbose = undef; # -v
+my $cvs_kill_keywords = undef; # -k
+my $convert_underscores = undef; # -u
+my $cvsroot = undef; # -d
+my $cvsps_options = undef; # -p
+my $git_repos_root = undef; # -C
+my $cvsps_fuzz = undef; # -z
+my $import_only = undef; # -i
+my $cvsps_output_file = undef; # -P
+my $branch_subst = undef, # -s
+my $detect_merges = undef; # -m
+my @more_merge_regexes = (); # -M
+my $author_conv_file = undef; # -A
+my $skip_paths = undef; # -S
+my $commit_limits = undef; # -L
+my $all_commits = undef; # -a
+my $remote_path = undef; # -r
+
+my %options = (
+ "h" => \$help,
+ "o=s" => \$branch_for_head,
+ "v" => \$verbose,
+ "k" => \$cvs_kill_keywords,
+ "u" => \$convert_underscores,
+ "d=s" => \$cvsroot,
+ "p=s" => \$cvsps_options,
+ "C=s" => \$git_repos_root,
+ "z=s" => \$cvsps_fuzz,
+ "i" => \$import_only,
+ "P=s" => \$cvsps_output_file,
+ "s=s" => \$branch_subst,
+ "m" => \$detect_merges,
+ "M=s" => \@more_merge_regexes,
+ "A=s" => \$author_conv_file,
+ "S=s" => \$skip_paths,
+ "L=s" => \$commit_limits,
+ "a" => \$all_commits,
+ "r=s" => \$remote_path
+);
+
my (%conv_author_name, %conv_author_email);
sub usage(;$) {
@@ -88,37 +132,46 @@ sub write_author_info($) {
close ($f);
}
-# convert getopts specs for use by git config
-sub read_repo_config {
- # Split the string between characters, unless there is a ':'
- # So "abc:de" becomes ["a", "b", "c:", "d", "e"]
- my @opts = split(/ *(?!:)/, shift);
- foreach my $o (@opts) {
- my $key = $o;
- $key =~ s/://g;
- my $arg = 'git config';
- $arg .= ' --bool' if ($o !~ /:$/);
-
- chomp(my $tmp = `$arg --get cvsimport.$key`);
- if ($tmp && !($arg =~ /--bool/ && $tmp eq 'false')) {
- no strict 'refs';
- my $opt_name = "opt_" . $key;
- if (!$$opt_name) {
- $$opt_name = $tmp;
- }
+sub read_repo_config ()
+{
+ while (my ($opt, $ref) = each %options) {
+ my $key = $opt;
+ my $is_boolean = 0;
+ my $cmd = "git config";
+ unless ($key =~ s/=s$//) {
+ $is_boolean = 1;
+ $cmd .= " --bool";
+ }
+ $cmd .= " cvsimport.$key";
+
+ chomp(my $tmp = qx/$cmd/);
+ $tmp or next;
+
+ if (ref($ref) eq "ARRAY") {
+ #
+ # FIXME: unhandled...
+ # However this could be handled by splitting $tmp with
+ # /\s*,\s*/ and pusing the result into @$ref (for the -M
+ # option)
+ #
+ next;
+ }
+
+ if ($is_boolean) {
+ $$ref = ("$tmp" eq "true") ? 1 : 0;
+ } else {
+ $$ref = "$tmp";
}
}
}
-my $opts = "haivmkuo:d:p:r:C:z:s:M:P:A:S:L:";
-read_repo_config($opts);
+
+read_repo_config();
Getopt::Long::Configure( 'no_ignore_case', 'bundling' );
-# turn the Getopt::Std specification in a Getopt::Long one,
-# with support for multiple -M options
-GetOptions( map { s/:/=s/; /M/ ? "$_\@" : $_ } split( /(?!:)/, $opts ) )
- or usage();
-usage if $opt_h;
+GetOptions(%options) or usage();
+
+usage() if $help;
if (@ARGV == 0) {
chomp(my $module = `git config --get cvsimport.module`);
@@ -126,31 +179,32 @@ if (@ARGV == 0) {
}
@ARGV <= 1 or usage("You can't specify more than one CVS module");
-if ($opt_d) {
- $ENV{"CVSROOT"} = $opt_d;
+if ($cvsroot) {
+ $ENV{"CVSROOT"} = $cvsroot;
} elsif (-f 'CVS/Root') {
open my $f, '<', 'CVS/Root' or die 'Failed to open CVS/Root';
- $opt_d = <$f>;
- chomp $opt_d;
+ $cvsroot = <$f>;
+ chomp $cvsroot;
close $f;
- $ENV{"CVSROOT"} = $opt_d;
+ $ENV{"CVSROOT"} = $cvsroot;
} elsif ($ENV{"CVSROOT"}) {
- $opt_d = $ENV{"CVSROOT"};
+ $cvsroot = $ENV{"CVSROOT"};
} else {
usage("CVSROOT needs to be set");
}
-$opt_s ||= "-";
-$opt_a ||= 0;
+$branch_subst ||= "-";
+$all_commits ||= 0;
-my $git_tree = $opt_C;
+my $git_tree = $git_repos_root;
$git_tree ||= ".";
my $remote;
-if (defined $opt_r) {
- $remote = 'refs/remotes/' . $opt_r;
- $opt_o ||= "master";
+
+if (defined $remote_path) {
+ $remote = 'refs/remotes/' . $remote_path;
+ $branch_for_head ||= "master";
} else {
- $opt_o ||= "origin";
+ $branch_for_head ||= "origin";
$remote = 'refs/heads';
}
@@ -168,11 +222,11 @@ if ($#ARGV == 0) {
}
our @mergerx = ();
-if ($opt_m) {
+if ($detect_merges) {
@mergerx = ( qr/\b(?:from|of|merge|merging|merged) ([-\w]+)/i );
}
-if (@opt_M) {
- push (@mergerx, map { qr/$_/ } @opt_M);
+if (@more_merge_regexes) {
+ push (@mergerx, map { qr/$_/ } @more_merge_regexes);
}
# Remember UTC of our starting time
@@ -370,7 +424,7 @@ sub _file {
$self->{'socketo'}->write("Argument -N\n") or return undef;
$self->{'socketo'}->write("Argument -P\n") or return undef;
# -kk: Linus' version doesn't use it - defaults to off
- if ($opt_k) {
+ if ($cvs_kill_keywords) {
$self->{'socketo'}->write("Argument -kk\n") or return undef;
}
$self->{'socketo'}->write("Argument -r\n") or return undef;
@@ -487,7 +541,7 @@ sub _fetchfile {
package main;
-my $cvs = CVSconn->new($opt_d, $cvs_tree);
+my $cvs = CVSconn->new($cvsroot, $cvs_tree);
sub pdate($) {
@@ -565,7 +619,7 @@ unless (-d $git_dir) {
system("git-read-tree");
die "Cannot init an empty tree: $?\n" if $?;
- $last_branch = $opt_o;
+ $last_branch = $branch_for_head;
$orig_branch = "";
} else {
open(F, "git-symbolic-ref HEAD |") or
@@ -592,8 +646,8 @@ unless (-d $git_dir) {
$branch_date{$head} = $1;
}
close(H);
- if (!exists $branch_date{$opt_o}) {
- die "Branch '$opt_o' does not exist.\n".
+ if (!exists $branch_date{$branch_for_head}) {
+ die "Branch '$branch_for_head' does not exist.\n".
"Either use the correct '-o branch' option,\n".
"or import to a new repository.\n";
}
@@ -605,31 +659,31 @@ unless (-d $git_dir) {
# now we read (and possibly save) author-info as well
-f "$git_dir/cvs-authors" and
read_author_info("$git_dir/cvs-authors");
-if ($opt_A) {
- read_author_info($opt_A);
+if ($author_conv_file) {
+ read_author_info($author_conv_file);
write_author_info("$git_dir/cvs-authors");
}
#
# run cvsps into a file unless we are getting
-# it passed as a file via $opt_P
+# it passed as a file via $cvsps_output_file
#
my $cvspsfile;
-unless ($opt_P) {
- print "Running cvsps...\n" if $opt_v;
+unless ($cvsps_output_file) {
+ print "Running cvsps...\n" if $verbose;
my $pid = open(CVSPS,"-|");
my $cvspsfh;
die "Cannot fork: $!\n" unless defined $pid;
unless ($pid) {
my @opt;
- @opt = split(/,/,$opt_p) if defined $opt_p;
- unshift @opt, '-z', $opt_z if defined $opt_z;
- unshift @opt, '-q' unless defined $opt_v;
- unless (defined($opt_p) && $opt_p =~ m/--no-cvs-direct/) {
+ @opt = split(/,/,$cvsps_options) if defined $cvsps_options;
+ unshift @opt, '-z', $cvsps_fuzz if defined $cvsps_fuzz;
+ unshift @opt, '-q' unless defined $verbose;
+ unless (defined($cvsps_options) && $cvsps_options =~ m/--no-cvs-direct/) {
push @opt, '--cvs-direct';
}
- exec("cvsps","--norc",@opt,"-u","-A",'--root',$opt_d,$cvs_tree);
+ exec("cvsps","--norc",@opt,"-u","-A",'--root',$cvsroot,$cvs_tree);
die "Could not start cvsps: $!\n";
}
($cvspsfh, $cvspsfile) = tempfile('gitXXXXXX', SUFFIX => '.cvsps',
@@ -641,7 +695,7 @@ unless ($opt_P) {
$? == 0 or die "git-cvsimport: fatal: cvsps reported error\n";
close $cvspsfh;
} else {
- $cvspsfile = $opt_P;
+ $cvspsfile = $cvsps_output_file;
}
open(CVS, "<$cvspsfile") or die $!;
@@ -688,7 +742,7 @@ sub write_tree () {
or die "Cannot get tree id ($tree): $!";
close($fh)
or die "Error running git-write-tree: $?\n";
- print "Tree ID $tree\n" if $opt_v;
+ print "Tree ID $tree\n" if $verbose;
return $tree;
}
@@ -699,7 +753,7 @@ my (@old,@new,@skipped,%ignorebranch);
$ignorebranch{'#CVSPS_NO_BRANCH'} = 1;
sub commit {
- if ($branch eq $opt_o && !$index{branch} &&
+ if ($branch eq $branch_for_head && !$index{branch} &&
!get_headref("$remote/$branch")) {
# looks like an initial commit
# use the index primed by git-init
@@ -725,7 +779,7 @@ sub commit {
@old = @new = ();
my $tree = write_tree();
my $parent = get_headref("$remote/$last_branch");
- print "Parent ID " . ($parent ? $parent : "(empty)") . "\n" if $opt_v;
+ print "Parent ID " . ($parent ? $parent : "(empty)") . "\n" if $verbose;
my @commit_args;
push @commit_args, ("-p", $parent) if $parent;
@@ -734,10 +788,10 @@ sub commit {
# based on the commit msg
foreach my $rx (@mergerx) {
next unless $logmsg =~ $rx && $1;
- my $mparent = $1 eq 'HEAD' ? $opt_o : $1;
+ my $mparent = $1 eq 'HEAD' ? $branch_for_head : $1;
if (my $sha1 = get_headref("$remote/$mparent")) {
push @commit_args, '-p', "$remote/$mparent";
- print "Merge parent branch: $mparent\n" if $opt_v;
+ print "Merge parent branch: $mparent\n" if $verbose;
}
}
@@ -764,10 +818,10 @@ sub commit {
print($commit_write "$logmsg\n") && close($commit_write)
or die "Error writing to git-commit-tree: $!\n";
- print "Committed patch $patchset ($branch $commit_date)\n" if $opt_v;
+ print "Committed patch $patchset ($branch $commit_date)\n" if $verbose;
chomp(my $cid = <$commit_read>);
is_sha1($cid) or die "Cannot get commit id ($cid): $!\n";
- print "Commit ID $cid\n" if $opt_v;
+ print "Commit ID $cid\n" if $verbose;
close($commit_read);
waitpid($pid,0);
@@ -779,14 +833,14 @@ sub commit {
if ($tag) {
my ($xtag) = $tag;
$xtag =~ s/\s+\*\*.*$//; # Remove stuff like ** INVALID ** and ** FUNKY **
- $xtag =~ tr/_/\./ if ( $opt_u );
- $xtag =~ s/[\/]/$opt_s/g;
+ $xtag =~ tr/_/\./ if ( $convert_underscores );
+ $xtag =~ s/[\/]/$branch_subst/g;
$xtag =~ s/\[//g;
system('git-tag', '-f', $xtag, $cid) == 0
or die "Cannot create tag $xtag: $!\n";
- print "Created tag '$xtag' on '$branch'\n" if $opt_v;
+ print "Created tag '$xtag' on '$branch'\n" if $verbose;
}
};
@@ -822,14 +876,14 @@ while (<CVS>) {
$state = 4;
} elsif ($state == 4 and s/^Branch:\s+//) {
s/\s+$//;
- tr/_/\./ if ( $opt_u );
- s/[\/]/$opt_s/g;
+ tr/_/\./ if ( $convert_underscores );
+ s/[\/]/$branch_subst/g;
$branch = $_;
$state = 5;
} elsif ($state == 5 and s/^Ancestor branch:\s+//) {
s/\s+$//;
$ancestor = $_;
- $ancestor = $opt_o if $ancestor eq "HEAD";
+ $ancestor = $branch_for_head if $ancestor eq "HEAD";
$state = 6;
} elsif ($state == 5) {
$ancestor = undef;
@@ -847,19 +901,19 @@ while (<CVS>) {
$logmsg = "";
$state = 8;
} elsif ($state == 8 and /^Members:/) {
- $branch = $opt_o if $branch eq "HEAD";
+ $branch = $branch_for_head if $branch eq "HEAD";
if (defined $branch_date{$branch} and $branch_date{$branch} >= $date) {
# skip
- print "skip patchset $patchset: $date before $branch_date{$branch}\n" if $opt_v;
+ print "skip patchset $patchset: $date before $branch_date{$branch}\n" if $verbose;
$state = 11;
next;
}
- if (!$opt_a && $starttime - 300 - (defined $opt_z ? $opt_z : 300) <= $date) {
+ if (!$all_commits && $starttime - 300 - (defined $cvsps_fuzz ? $cvsps_fuzz : 300) <= $date) {
# skip if the commit is too recent
# given that the cvsps default fuzz is 300s, we give ourselves another
# 300s just in case -- this also prevents skipping commits
# due to server clock drift
- print "skip patchset $patchset: $date too recent\n" if $opt_v;
+ print "skip patchset $patchset: $date too recent\n" if $verbose;
$state = 11;
next;
}
@@ -870,8 +924,8 @@ while (<CVS>) {
}
if ($ancestor) {
if ($ancestor eq $branch) {
- print STDERR "Branch $branch erroneously stems from itself -- changed ancestor to $opt_o\n";
- $ancestor = $opt_o;
+ print STDERR "Branch $branch erroneously stems from itself -- changed ancestor to $branch_for_head\n";
+ $ancestor = $branch_for_head;
}
if (defined get_headref("$remote/$branch")) {
print STDERR "Branch $branch already exists!\n";
@@ -905,18 +959,18 @@ while (<CVS>) {
my $fn = $1;
my $rev = $3;
$fn =~ s#^/+##;
- if ($opt_S && $fn =~ m/$opt_S/) {
+ if ($skip_paths && $fn =~ m/$skip_paths/) {
print "SKIPPING $fn v $rev\n";
push(@skipped, $fn);
next;
}
- print "Fetching $fn v $rev\n" if $opt_v;
+ print "Fetching $fn v $rev\n" if $verbose;
my ($tmpname, $size) = $cvs->file($fn,$rev);
if ($size == -1) {
push(@old,$fn);
- print "Drop $fn\n" if $opt_v;
+ print "Drop $fn\n" if $verbose;
} else {
- print "".($init ? "New" : "Update")." $fn: $size bytes\n" if $opt_v;
+ print "".($init ? "New" : "Update")." $fn: $size bytes\n" if $verbose;
my $pid = open(my $F, '-|');
die $! unless defined $pid;
if (!$pid) {
@@ -934,12 +988,12 @@ while (<CVS>) {
my $fn = $1;
$fn =~ s#^/+##;
push(@old,$fn);
- print "Delete $fn\n" if $opt_v;
+ print "Delete $fn\n" if $verbose;
} elsif ($state == 9 and /^\s*$/) {
$state = 10;
} elsif (($state == 9 or $state == 10) and /^-+$/) {
$commitcount++;
- if ($opt_L && $commitcount > $opt_L) {
+ if ($commit_limits && $commitcount > $commit_limits) {
last;
}
commit();
@@ -957,7 +1011,7 @@ while (<CVS>) {
}
commit() if $branch and $state != 11;
-unless ($opt_P) {
+unless ($cvsps_output_file) {
unlink($cvspsfile);
}
@@ -985,31 +1039,31 @@ if (defined $orig_git_index) {
# Now switch back to the branch we were in before all of this happened
if ($orig_branch) {
- print "DONE.\n" if $opt_v;
- if ($opt_i) {
+ print "DONE.\n" if $verbose;
+ if ($import_only) {
exit 0;
}
my $tip_at_end = `git-rev-parse --verify HEAD`;
if ($tip_at_start ne $tip_at_end) {
for ($tip_at_start, $tip_at_end) { chomp; }
- print "Fetched into the current branch.\n" if $opt_v;
+ print "Fetched into the current branch.\n" if $verbose;
system(qw(git-read-tree -u -m),
$tip_at_start, $tip_at_end);
die "Fast-forward update failed: $?\n" if $?;
}
else {
- system(qw(git-merge cvsimport HEAD), "$remote/$opt_o");
- die "Could not merge $opt_o into the current branch.\n" if $?;
+ system(qw(git-merge cvsimport HEAD), "$remote/$branch_for_head");
+ die "Could not merge $branch_for_head into the current branch.\n" if $?;
}
} else {
$orig_branch = "master";
- print "DONE; creating $orig_branch branch\n" if $opt_v;
- system("git-update-ref", "refs/heads/master", "$remote/$opt_o")
+ print "DONE; creating $orig_branch branch\n" if $verbose;
+ system("git-update-ref", "refs/heads/master", "$remote/$branch_for_head")
unless defined get_headref('refs/heads/master');
- system("git-symbolic-ref", "$remote/HEAD", "$remote/$opt_o")
- if ($opt_r && $opt_o ne 'HEAD');
+ system("git-symbolic-ref", "$remote/HEAD", "$remote/$branch_for_head")
+ if ($remote_path && $branch_for_head ne 'HEAD');
system('git-update-ref', 'HEAD', "$orig_branch");
- unless ($opt_i) {
+ unless ($import_only) {
system('git checkout -f');
die "checkout failed: $?\n" if $?;
}
--
1.6.0.3
--
fge
^ permalink raw reply related
* Re: [Q] Abbreviated history graph?
From: Brian Foster @ 2008-11-03 15:46 UTC (permalink / raw)
To: Santi Béjar; +Cc: Git Mailing List
In-Reply-To: <adf1fd3d0811030620x1bc53db3y2afb26242e9906ac@mail.gmail.com>
On Monday 03 November 2008 15:20:30 Santi Béjar wrote:
>[ ... ]
> > Is there some way of doing something similar [ the example ]
> > (git v1.6.0.2)? In addition to 'gitk', we also (rather
> > quickly!) tried both 'qgit' and 'giggle', but without
> > any apparent success.
>
> Not in git.git but you can use the script at the bottom [ ... ].
Santi,
Thanks. Unfortunately, neither I nor my colleague can try
it at the moment: It uses `git log --pretty=format:%d'
which is very new (added c.9-Sept) and not in the versions
of git we are currently using. End result is the tempfile
is always empty, and hence `gitk' shows everything.
cheers!
-blf-
--
“How many surrealists does it take to | Brian Foster
change a lightbulb? Three. One calms | somewhere in south of France
the warthog, and two fill the bathtub | Stop E$$o (ExxonMobil)!
with brightly-coloured machine tools.” | http://www.stopesso.com
^ permalink raw reply
* Re: CRLF support bugs
From: Hannu Koivisto @ 2008-11-03 15:25 UTC (permalink / raw)
To: git; +Cc: Jeff King
In-Reply-To: <83y700alzf.fsf_-_@kalahari.s2.org>
Hannu Koivisto <azure@iki.fi> writes:
> Actually, even if .gitattributes were applied in checkout, I think
> the whole CRLF support is broken by design because people will have
> to remember to use -n in clone, then enable core.autocrlf support
> and then checkout. This makes it unneccessarily complicated to
I forgot one thing: so what if someone forgets to use -n or just
imagines that you can set core.autocrlf afterwards?
# Pretend someone does this on Unix
mkdir test1
cd test1
git init
echo "*.c crlf" > .gitattributes
echo -e "foo\nfoo\nfoo" > kala.c
git add .gitattributes kala.c
git commit -m "Initial checkin."
cd ..
# Pretend test1 is not a local repository and someone else does this on Windows
git clone test1 test2
cd test2
git config core.autocrlf true
git status
# On branch master
nothing to commit (working directory clean)
Now the user would have to know that even though git status claims
everything is ok, that is not the case. The user would have to
know to say (according to #git):
rm .git/index
git reset --hard
Just for the record, when I started to learn git, one of the first
questions I had was "how do I undo checkout?" It wasn't until now
that I learned I need to remove .git/index (in addition to all
files).
--
Hannu
^ permalink raw reply
* Re: [PATCH] filter-branch: add git_commit_non_empty_tree and --prune-empty.
From: Pierre Habouzit @ 2008-11-03 15:18 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, pasky, srabbelier
In-Reply-To: <20081103092729.GE13930@artemis.corp>
[-- Attachment #1: Type: text/plain, Size: 6210 bytes --]
On Mon, Nov 03, 2008 at 09:27:29AM +0000, Pierre Habouzit wrote:
> On Mon, Nov 03, 2008 at 04:58:44AM +0000, Junio C Hamano wrote:
> > > diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
> > > index b0a9d7d..352b56b 100755
> > > --- a/t/t7003-filter-branch.sh
> > > +++ b/t/t7003-filter-branch.sh
> > > @@ -262,4 +262,12 @@ test_expect_success 'Tag name filtering allows slashes in tag names' '
> > > test_cmp expect actual
> > > '
> > >
> > > +test_expect_success 'Prune empty commits' '
> > > + make_commit to_remove &&
> > > + (git rev-list HEAD | grep -v $(git rev-parse HEAD)) > expect &&
> >
> > I am not sure what this one is doing.
> >
> > - Isn't this the same as "git rev-list HEAD^"?
> > - Do you need a subshell?
>
> The filter-branch is supposed to prune the last commit done (current
> HEAD) from the revision list. So I build the rev-list we're supposed to
> have in the end, and remove the matching ref from it. I don't see how to
> avoid the subshell though, but if someone knows better please do :)
Actually one can write the test this way:
test_expect_success 'Prune empty commits' '
git rev-list HEAD > expect &&
make_commit to_remove &&
git filter-branch -f --index-filter "git update-index --remove to_remove" --prune-empty HEAD &&
git rev-list HEAD > actual &&
test_cmp expect actual
'
Which basically:
- remembers the current list of revisions,
- makes a commit,
- runs an index-filter that makes that last commit void,
- checks the last commit has been removed.
below is the updated patch with your comment and this fix
---8<---
From: Pierre Habouzit <madcoder@debian.org>
Date: Fri, 31 Oct 2008 10:12:21 +0100
Subject: [PATCH] filter-branch: add git_commit_non_empty_tree and --prune-empty.
git_commit_non_empty_tree is added to the functions that can be run from
commit filters. Its effect is to commit only commits actually touching the
tree and that are not merge points either.
The option --prune-empty is added. It defaults the commit-filter to
'git_commit_non_empty_tree "$@"', and can be used with any other
combination of filters, except --commit-hook that must used
'git_commit_non_empty_tree "$@"' where one puts 'git commit-tree "$@"'
usually to achieve the same result.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
Documentation/git-filter-branch.txt | 14 ++++++++++++++
git-filter-branch.sh | 29 ++++++++++++++++++++++++++++-
t/t7003-filter-branch.sh | 8 ++++++++
3 files changed, 50 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-filter-branch.txt b/Documentation/git-filter-branch.txt
index fed6de6..451950b 100644
--- a/Documentation/git-filter-branch.txt
+++ b/Documentation/git-filter-branch.txt
@@ -122,6 +122,10 @@ You can use the 'map' convenience function in this filter, and other
convenience functions, too. For example, calling 'skip_commit "$@"'
will leave out the current commit (but not its changes! If you want
that, use 'git-rebase' instead).
++
+You can also use the 'git_commit_non_empty_tree "$@"' instead of
+'git commit-tree "$@"' if you don't wish to keep commits with a single parent
+and that makes no change to the tree.
--tag-name-filter <command>::
This is the filter for rewriting tag names. When passed,
@@ -151,6 +155,16 @@ to other tags will be rewritten to point to the underlying commit.
The result will contain that directory (and only that) as its
project root.
+--prune-empty::
+ Some kind of filters will generate empty commits, that left the tree
+ untouched. This switch allow git-filter-branch to ignore such
+ commits. Though, this switch only applies for commits that have one
+ and only one parent, it will hence keep merges points. Also, this
+ option is not compatible with the use of '--commit-filter'. Though you
+ just need to use the function 'git_commit_non_empty_tree "$@"' instead
+ of the 'git commit-tree "$@"' idiom in your commit filter to make that
+ happen.
+
--original <namespace>::
Use this option to set the namespace where the original commits
will be stored. The default value is 'refs/original'.
diff --git a/git-filter-branch.sh b/git-filter-branch.sh
index 81392ad..331724d 100755
--- a/git-filter-branch.sh
+++ b/git-filter-branch.sh
@@ -40,6 +40,16 @@ skip_commit()
done;
}
+# if you run 'git_commit_non_empty_tree "$@"' in a commit filter,
+# it will skip commits that leave the tree untouched, commit the other.
+git_commit_non_empty_tree()
+{
+ if test $# = 3 && test "$1" = $(git rev-parse "$3^{tree}"); then
+ map "$3"
+ else
+ git commit-tree "$@"
+ fi
+}
# override die(): this version puts in an extra line break, so that
# the progress is still visible
@@ -109,11 +119,12 @@ filter_tree=
filter_index=
filter_parent=
filter_msg=cat
-filter_commit='git commit-tree "$@"'
+filter_commit=
filter_tag_name=
filter_subdir=
orig_namespace=refs/original/
force=
+prune_empty=
while :
do
case "$1" in
@@ -126,6 +137,11 @@ do
force=t
continue
;;
+ --prune-empty)
+ shift
+ prune_empty=t
+ continue
+ ;;
-*)
;;
*)
@@ -176,6 +192,17 @@ do
esac
done
+case "$prune_empty,$filter_commit" in
+,)
+ filter_commit='git commit-tree "$@"';;
+t,)
+ filter_commit="$functions;"' git_commit_non_empty_tree "$@"';;
+,*)
+ ;;
+*)
+ die "Cannot set --prune-empty and --filter-commit at the same time"
+esac
+
case "$force" in
t)
rm -rf "$tempdir"
diff --git a/t/t7003-filter-branch.sh b/t/t7003-filter-branch.sh
index b0a9d7d..8537bf9 100755
--- a/t/t7003-filter-branch.sh
+++ b/t/t7003-filter-branch.sh
@@ -262,4 +262,12 @@ test_expect_success 'Tag name filtering allows slashes in tag names' '
test_cmp expect actual
'
+test_expect_success 'Prune empty commits' '
+ git rev-list HEAD > expect &&
+ make_commit to_remove &&
+ git filter-branch -f --index-filter "git update-index --remove to_remove" --prune-empty HEAD &&
+ git rev-list HEAD > actual &&
+ test_cmp expect actual
+'
+
test_done
--
1.6.0.3.795.g892be
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply related
* CRLF support bugs (was: Re: .gitattributes glob matching broken)
From: Hannu Koivisto @ 2008-11-03 15:05 UTC (permalink / raw)
To: git; +Cc: Jeff King
In-Reply-To: <20081103090932.GA18424@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> I think your analysis is incorrect. I will try to explain what is
> happening.
Yes, you are right. The behaviour I saw in my actual use case was
so odd that I got completely confused.
I suspect one part of that "oddness" was caused by git applying its
heuristics in checkout as it doesn't use .gitattributes at that
time. For example, it seems that it recognized some of my .sh
files as text files and the rest as binary files. I suppose I was
correct to assume that it would be stupid to rely on git guessing
file type and the only sensible way is to use .gitattributes. If
it was supported in checkout too, that is.
I don't know what purpose the autodetection aims to serve but I'd
add a big warning in the core.autocrlf documentation about it and
instructions on how to configure things so that it is never applied
but instead the types must always be specified explicitly.
> The problem, again, is that we have inconsistently applied the
> gitattributes. They were _not_ applied during checkout (because
> .gitattributes did not exist yet), but they _are_ being applied here.
>
> To "fix" this, you can then do a "git reset --hard" which will respect
> your .gitattributes (since it is now checked out). And further file
> creation and checkout should work OK.
Since I'm trying to launch git in a company environment, I think I
can't rely on people remembering to do that.
Actually, even if .gitattributes were applied in checkout, I think
the whole CRLF support is broken by design because people will have
to remember to use -n in clone, then enable core.autocrlf support
and then checkout. This makes it unneccessarily complicated to
create "quick local clones" as well. You might suggest that
Windows users should enable core.autocrlf globally but it may not
be the right thing to do for all projects/repositories either.
I think CRLF conversion support should have some attribute (be it
.gitattributes attribute or something else) that is somehow
inherited from the parent repository. It would basically say that
"you should use platform's native line end type for text files with
this repository and its children". To go with that, one would
maybe have a configuration option to tell what that platform
default line end type is (just in case someone wants to pretend
Cygwin is Unix or something like that).
I also observed this problem:
# Pretend someone does this on Unix
mkdir test1
cd test1
git init
echo "*.c crlf" > .gitattributes
echo -en "foo\r\nfoo\r\nfoo\r\n" > kala.c
git add .gitattributes kala.c
git commit -m "* Initial checkin."
cd ..
# Pretend someone else does this on Windows
git clone -n test1 test2
cd test2
git config core.autocrlf true
git checkout
git status
...
# modified: kala.c
...
git reset --hard
git status
...
# modified: kala.c
...
Now, even if .gitattributes were obeyed by checkout, I suspect the end
result would be the same(?) I'm sure someone argues that this makes
sense. But try to put yourself in the position of a random Window
user. I think it's far from obvious what is going on and what
should be done in this situation.
--
Hannu
^ permalink raw reply
* Re: [Q] Abbreviated history graph?
From: Santi Béjar @ 2008-11-03 14:55 UTC (permalink / raw)
To: Brian Foster; +Cc: Git Mailing List
In-Reply-To: <adf1fd3d0811030620x1bc53db3y2afb26242e9906ac@mail.gmail.com>
On Mon, Nov 3, 2008 at 3:20 PM, Santi Béjar <santi@agolina.net> wrote:
> On Mon, Nov 3, 2008 at 2:39 PM, Brian Foster
> <brian.foster@innova-card.com> wrote:
>>
>> Hello,
>>
>> A colleague and I recently wanted to examine the
>> history in a broad sense without worrying too much
>> about the individual commits. What we (think we)
>> wanted is a 'gitk --all' history graph showing only
>> "named" historical points; i.e., tags and branch
>> HEADs, perhaps with an indication of whether or not
>> it's a "linear" change sequence that leads from one
>> to another. That is, hypothetically, if the history
>> looks something like (where 'A' &tc has a name as
>> per above, and '*' does not):
>>
>> A--->*--->*--->C--->D--->*----->E
>> \ \ /
>> \->*-->B \->*--->*--->F
>>
>> What we wanted to see is something like:
>>
>> A------>C--->D--->E
>> \ \ /
>> \->B \-----/--->F
>>
>> Is there some way of doing something similar to that
>> (git v1.6.0.2)? In addition to 'gitk', we also (rather
>> quickly!) tried both 'qgit' and 'giggle', but without
>> any apparent success.
>
> Not in git.git but you can use the script at the bottom (also attached
> in case it is whitespace damage).
> It could be much faster if "git log" stops when finding a tag/branch.
>
Just to add that it would be great if gitk's "List references" showed
them in this way (possibly with a toggle to show them in alphabetical
order).
Santi
^ permalink raw reply
* Re: git-cvsimport BUG: some commits are completely out of phase (but cvsps sees them all right)
From: Michael Haggerty @ 2008-11-03 14:52 UTC (permalink / raw)
To: Francis Galiegue; +Cc: tomi.pakarinen, git
In-Reply-To: <200811022331.14048.fg@one2team.net>
Francis Galiegue wrote:
> The plan would be to convert all modules in one go, with no one committing in
> the meantime, so that's not a problem.
Then you should definitely try cvs2svn/cvs2git [1]. cvsps-based
conversion tools all have known and unavoidable problems due to the
limitations of cvsps.
Michael
(the cvs2svn/cvs2git maintainer)
[1] http://cvs2svn.tigris.org/cvs2git.html
^ permalink raw reply
* Re: [Announce] teamGit v0.0.4
From: Abhijit Bhopatkar @ 2008-11-03 14:49 UTC (permalink / raw)
To: Ping Yin, git
In-Reply-To: <20081103134654.GA13989@kooxoo235>
On Mon, Nov 3, 2008 at 7:16 PM, Ping Yin <pkufranky@gmail.com> wrote:
> * Abhijit Bhopatkar <bain@devslashzero.com> [2008-11-03 19:05:24 +0530]:
>> teamGit is a GUI for git,
>> in its final roadmap it aims to aid small closed teams to use git,
>> currently its a pretty good frontend for basic git operations.
> Can it be used on windows?
I have just finished pushing some trivial changes to make it compile
and work on windows, I tested it with latest msysgit and it seems to
work fine, although this really is just a 5 min. test.
You will need qt 4.4.3 with mingw toolchain installed to compile this,
i do not have expertise and/or will to create a installer etc. but
patches/additions are welcome if someone can take this up.
Abhijit
^ permalink raw reply
* Git SVN Rebranching Issue
From: Matt Kern @ 2008-11-03 14:07 UTC (permalink / raw)
To: git
I have a git-svn issue which keeps biting me.
My company uses svn as its primary version control system. We
frequently create branches, e.g. /branches/somebranch, by forking the
trunk to ensure stability over the "somebranch" code. The problem is
that we also frequently blow away /branches/somebranch and refork it
from the trunk.
git-svn does a good job for most work, but I notice that if you delete
the "somebranch" branch in svn and then refork it, also in svn, then
when you git-svn fetch, the git commit at the head of remotes/somebranch
will have two parents: the first is the previous head of
remotes/somebranch, and the second is the head of remotes/trunk. Surely
only the remotes/trunk parent should be listed? Any connection with the
previous remotes/somebranch is an accident of naming. The real problem
then comes when you come to look at the history in gitk. If
"somebranch" is rebranched many times, the git history starts looking
pretty complicated, when in fact it should simply be the linear history
of remotes/trunk up to the branch point followed by a few,
branch-specific commits. Is there any way to prevent (or modify) the
git history to remove the errant parent?
In the ideal world, we wouldn't reuse branch names in svn, but it is
convenient and doesn't cause problems for svn users. I can't force the
rest of the company to change to accommodate my use of git...
I am using git (svn) version 1.5.6.5 (svn 1.4.6) from Debian/Lenny and
can provide a trivial repository demonstrating the problem if anyone is
interested.
Matt
--
Matt Kern
http://www.undue.org/
^ 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