Git development
 help / color / mirror / Atom feed
* Re: What's cooking in git/spearce.git (topics)
From: Steffen Prohaska @ 2007-10-22 15:27 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Shawn O. Pearce
In-Reply-To: <20071022063222.GS14735@spearce.org>


On Oct 22, 2007, at 8:32 AM, Shawn O. Pearce wrote:

> * sp/push-refspec (Sun Oct 14 10:54:45 2007 +0200) 6 commits
>  - push, send-pack: use same rules as git-rev-parse to resolve
>    refspecs
>  - add ref_cmp_full_short() comparing full ref name with a short name
>  - push, send-pack: support pushing HEAD to real ref name
>  - rev-parse: teach "git rev-parse --symbolic" to print the full ref
>    name
>  - add get_sha1_with_real_ref() returning full name of ref on demand
>  - push, send-pack: fix test if remote branch exists for colon-less
>    refspec
>
> I've briefly looked at this series and there's reasons why its not
> in next yet.

It's not ready for next. Especially the last patch in the list
changes the existing behaviour in a way that might be unexpected
by longtime git users. And maybe we even need for the 1.6 cycle
before we can change the behaviour of git push.


> Its actually something that I'm interested in seeing
> fixed as the current behavior of how git-push matches refs on the
> remote side is just plain nuts.  I'll look at it further after I
> get ph/parseopt and cc/skip into next.

I planned to draw a conclusion from the discussion in

http://marc.info/?l=git&m=119286893014690&w=2

and send an updated proposal based on what I learnt. But
unfortunately I didn't have time yet.

My impression now is that the details of the behaviour of "git
push" are hard to understand and should be made more explicit.

Related tasks are currently encoded in the refspecs, but the
details are not always obvious right away:
- creation of new branches on the remote side.
- deletion of branches on the remote side.
- pushing of branches matching on local and remote side.
- pushing local branches explicitly to a different ref on the remote.
- save newbies from pushing to 'non-standard' location, that
   is only push to heads and tags.
- but also allow to push to funny refs if you force git to
   do this.

All this is related to the topic above, although its maybe too much
to be solved at once.

	Steffen

^ permalink raw reply

* Re: [PATCH] execv_git_cmd(): also try PATH if everything else fails.
From: Johannes Sixt @ 2007-10-22 15:36 UTC (permalink / raw)
  To: Andreas Ericsson, Scott Parish; +Cc: Johannes Schindelin, Shawn O. Pearce, git
In-Reply-To: <471CBF88.6020300@op5.se>

Andreas Ericsson schrieb:
> Scott Parish wrote:
>> I'm tempted to try a different approach. What if instead of looping
>> and building up strings of all the different absolute paths we want
>> to try we just prepend to PATH with the correct extra precedence,
>> and then call execvp on the command we want?
>>
> 
> That's how the original git --exec-dir feature got implemented. There's 
> even a nifty function for it in git.c; prepend_to_path(). It's a 
> provably workable solution.

The reason that this was done is for the sake of shell scripts: They need to 
have the path that was finally decided as exec-path in $PATH.

But I can't think of any negative side effect if *all* exec-path candidates 
are in $PATH. It's important, though, that all paths are absolute because 
the tools chdir every now and then.

-- Hannes

^ permalink raw reply

* Re: [PATCH, take 1] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 16:33 UTC (permalink / raw)
  To: skimo
  Cc: Git Mailing List, Junio C Hamano, Shawn O. Pearce, David Kastrup,
	Jeff King
In-Reply-To: <20071022070750.GM1179MdfPADPa@greensroom.kotnet.org>



On Mon, 22 Oct 2007, Sven Verdoolaege wrote:
> 
> Aren't you truncating the ptr list after the first entry here?
> (While you still need the whole list in free_file_table.)

Yes. I didn't have that bug in the first version (I didn't do a separate 
"free_file_table()" at all - I just free'd the src/dst pointer lists at 
the end of that function). But I wanted to "clean up" the thing. Duh.

		Linus

^ permalink raw reply

* odd behavior with concurrent fetch/checkout
From: J. Bruce Fields @ 2007-10-22 16:51 UTC (permalink / raw)
  To: git

Just now I checked out a topic branch in my working repo:

	git checkout server-xprt-switch

and while waiting for it to complete (I just started work and caches
were all cold), I ran a

	git fetch origin

in another window to update from Linus.  The git fetch gave a warning:

	remote: Generating pack...
	remote: Counting objects: 7550
	remote: Done counting 12885 objects.
	remote: Result has 8400 objects.
	remote: Deltifying 8400 objects...
	remote:  100% (8400/8400) done
	Indexing 8400 objects...
	remote: Total 8400 (delta 7257), reused 5696 (delta 4586)
	 100% (8400/8400) done
	Resolving 7257 deltas...
	 100% (7257/7257) done
	* refs/remotes/origin/master: fast forward to branch 'master' of
	* git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
	  old..new: d85714d..55b70a0
	Cannot fetch into the current branch.

Why the warning?  Also, afterwards I was left with server-xprt-switch
pointing to the tip of the branch I'd just switched from (another
miscellaneous topic branch).  The working directory was in some
completely different state--thanks to a quick reset --hard I don't know
what it was.  Also, in the reflog for the checked-out branch:

	commit bac1e7977eb4781e62cee7f1c7c3d13a9e5d8d74
	Reflog: server-xprt-switch@{0} (J. Bruce Fields <bfields@citi.umich.edu>)
	Reflog message: fetch origin: Undoing incorrectly fetched HEAD.
	Author: J. Bruce Fields <bfields@citi.umich.edu>
	Date:   Mon Oct 22 12:32:37 2007 -0400
	...

Why was a fetch into the remote fooling with HEAD or anything under
refs/heads/?

--b.

^ permalink raw reply

* [PATCH] "current_exec_path" is a misleading name, use "argv_exec_path"
From: Scott R Parish @ 2007-10-22 17:01 UTC (permalink / raw)
  To: git

 Signed-off-by: Scott R Parish <srp@srparish.net>

---
 exec_cmd.c |   12 ++++++------
 exec_cmd.h |    2 +-
 git.c      |    2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/exec_cmd.c b/exec_cmd.c
index 9b74ed2..8b681d0 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -5,11 +5,11 @@
 
 extern char **environ;
 static const char *builtin_exec_path = GIT_EXEC_PATH;
-static const char *current_exec_path;
+static const char *argv_exec_path = 0;
 
-void git_set_exec_path(const char *exec_path)
+void git_set_argv_exec_path(const char *exec_path)
 {
-	current_exec_path = exec_path;
+	argv_exec_path = exec_path;
 }
 
 
@@ -18,8 +18,8 @@ const char *git_exec_path(void)
 {
 	const char *env;
 
-	if (current_exec_path)
-		return current_exec_path;
+	if (argv_exec_path)
+		return argv_exec_path;
 
 	env = getenv(EXEC_PATH_ENVIRONMENT);
 	if (env && *env) {
@@ -34,7 +34,7 @@ int execv_git_cmd(const char **argv)
 {
 	char git_command[PATH_MAX + 1];
 	int i;
-	const char *paths[] = { current_exec_path,
+	const char *paths[] = { argv_exec_path,
 				getenv(EXEC_PATH_ENVIRONMENT),
 				builtin_exec_path };
 
diff --git a/exec_cmd.h b/exec_cmd.h
index 849a839..da99287 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -1,7 +1,7 @@
 #ifndef GIT_EXEC_CMD_H
 #define GIT_EXEC_CMD_H
 
-extern void git_set_exec_path(const char *exec_path);
+extern void git_set_argv_exec_path(const char *exec_path);
 extern const char* git_exec_path(void);
 extern int execv_git_cmd(const char **argv); /* NULL terminated */
 extern int execl_git_cmd(const char *cmd, ...);
diff --git a/git.c b/git.c
index e1c99e3..f659338 100644
--- a/git.c
+++ b/git.c
@@ -51,7 +51,7 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
 		if (!prefixcmp(cmd, "--exec-path")) {
 			cmd += 11;
 			if (*cmd == '=')
-				git_set_exec_path(cmd + 1);
+				git_set_argv_exec_path(cmd + 1);
 			else {
 				puts(git_exec_path());
 				exit(0);
-- 
gitgui.0.8.4.11176.gd9205-dirty

^ permalink raw reply related

* [PATCH] use only the PATH for exec'ing git commands
From: Scott R Parish @ 2007-10-22 17:01 UTC (permalink / raw)
  To: git

We need to correctly set up PATH for non-c based git commands. Since we
already do this, we can just use that PATH and execvp, instead of looping
over the paths with execve.

This patch adds a setup_path() function to exec_cmd.c, which sets
the PATH order correctly for our search order. execv_git_cmd() is
stripped down to setting up argv and calling execvp(). git.c's main()
only only needs to call setup_path().

Signed-off-by: Scott R Parish <srp@srparish.net>
---
 exec_cmd.c |  122 ++++++++++++++++++++++++++----------------------------------
 exec_cmd.h |    1 +
 git.c      |   43 +++------------------
 3 files changed, 61 insertions(+), 105 deletions(-)

diff --git a/exec_cmd.c b/exec_cmd.c
index 8b681d0..b154c24 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -29,85 +29,69 @@ const char *git_exec_path(void)
 	return builtin_exec_path;
 }
 
+static void add_path(struct strbuf *out, const char *path)
+{
+	if (path && strlen(path)) {
+		if (is_absolute_path(path))
+			strbuf_addstr(out, path);
+		else
+			strbuf_addstr(out, make_absolute_path(path));
+
+		strbuf_addch(out, ':');
+	}
+}
+
+void setup_path(const char *cmd_path)
+{
+	const char *old_path = getenv("PATH");
+	struct strbuf new_path;
+
+	strbuf_init(&new_path, 0);
+
+	add_path(&new_path, argv_exec_path);
+	add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
+	add_path(&new_path, builtin_exec_path);
+	add_path(&new_path, cmd_path);
+		
+	if (old_path)
+		strbuf_addstr(&new_path, old_path);
+	else 
+		strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");
+
+	setenv("PATH", new_path.buf, 1);
+
+	strbuf_release(&new_path);
+}
+
 
 int execv_git_cmd(const char **argv)
 {
-	char git_command[PATH_MAX + 1];
-	int i;
-	const char *paths[] = { argv_exec_path,
-				getenv(EXEC_PATH_ENVIRONMENT),
-				builtin_exec_path };
-
-	for (i = 0; i < ARRAY_SIZE(paths); ++i) {
-		size_t len;
-		int rc;
-		const char *exec_dir = paths[i];
-		const char *tmp;
-
-		if (!exec_dir || !*exec_dir) continue;
-
-		if (*exec_dir != '/') {
-			if (!getcwd(git_command, sizeof(git_command))) {
-				fprintf(stderr, "git: cannot determine "
-					"current directory: %s\n",
-					strerror(errno));
-				break;
-			}
-			len = strlen(git_command);
-
-			/* Trivial cleanup */
-			while (!prefixcmp(exec_dir, "./")) {
-				exec_dir += 2;
-				while (*exec_dir == '/')
-					exec_dir++;
-			}
-
-			rc = snprintf(git_command + len,
-				      sizeof(git_command) - len, "/%s",
-				      exec_dir);
-			if (rc < 0 || rc >= sizeof(git_command) - len) {
-				fprintf(stderr, "git: command name given "
-					"is too long.\n");
-				break;
-			}
-		} else {
-			if (strlen(exec_dir) + 1 > sizeof(git_command)) {
-				fprintf(stderr, "git: command name given "
-					"is too long.\n");
-				break;
-			}
-			strcpy(git_command, exec_dir);
-		}
-
-		len = strlen(git_command);
-		rc = snprintf(git_command + len, sizeof(git_command) - len,
-			      "/git-%s", argv[0]);
-		if (rc < 0 || rc >= sizeof(git_command) - len) {
-			fprintf(stderr,
-				"git: command name given is too long.\n");
-			break;
-		}
+	struct strbuf cmd;
+	const char *tmp;
 
-		/* argv[0] must be the git command, but the argv array
-		 * belongs to the caller, and my be reused in
-		 * subsequent loop iterations. Save argv[0] and
-		 * restore it on error.
-		 */
+	strbuf_init(&cmd, 0);
+	strbuf_addf(&cmd, "git-%s", argv[0]);
 
-		tmp = argv[0];
-		argv[0] = git_command;
+	/* argv[0] must be the git command, but the argv array
+	 * belongs to the caller, and my be reused in
+	 * subsequent loop iterations. Save argv[0] and
+	 * restore it on error.
+	 */
+	tmp = argv[0];
+	argv[0] = cmd.buf;
 
-		trace_argv_printf(argv, -1, "trace: exec:");
+	trace_argv_printf(argv, -1, "trace: exec:");
 
-		/* execve() can only ever return if it fails */
-		execve(git_command, (char **)argv, environ);
+	/* execvp() can only ever return if it fails */
+	execvp(cmd.buf, (char **)argv);
 
-		trace_printf("trace: exec failed: %s\n", strerror(errno));
+	trace_printf("trace: exec failed: %s\n", strerror(errno));
 
-		argv[0] = tmp;
-	}
-	return -1;
+	argv[0] = tmp;
 
+	strbuf_release(&cmd);
+
+	return -1;
 }
 
 
diff --git a/exec_cmd.h b/exec_cmd.h
index da99287..a892355 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -3,6 +3,7 @@
 
 extern void git_set_argv_exec_path(const char *exec_path);
 extern const char* git_exec_path(void);
+extern void setup_path(const char *);
 extern int execv_git_cmd(const char **argv); /* NULL terminated */
 extern int execl_git_cmd(const char *cmd, ...);
 
diff --git a/git.c b/git.c
index f659338..a639e42 100644
--- a/git.c
+++ b/git.c
@@ -6,28 +6,6 @@
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
 
-static void prepend_to_path(const char *dir, int len)
-{
-	const char *old_path = getenv("PATH");
-	char *path;
-	int path_len = len;
-
-	if (!old_path)
-		old_path = "/usr/local/bin:/usr/bin:/bin";
-
-	path_len = len + strlen(old_path) + 1;
-
-	path = xmalloc(path_len + 1);
-
-	memcpy(path, dir, len);
-	path[len] = ':';
-	memcpy(path + len + 1, old_path, path_len - len);
-
-	setenv("PATH", path, 1);
-
-	free(path);
-}
-
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
 	int handled = 0;
@@ -403,7 +381,7 @@ int main(int argc, const char **argv)
 {
 	const char *cmd = argv[0] ? argv[0] : "git-help";
 	char *slash = strrchr(cmd, '/');
-	const char *exec_path = NULL;
+	const char *cmd_path = NULL;
 	int done_alias = 0;
 
 	/*
@@ -413,10 +391,7 @@ int main(int argc, const char **argv)
 	 */
 	if (slash) {
 		*slash++ = 0;
-		if (*cmd == '/')
-			exec_path = cmd;
-		else
-			exec_path = xstrdup(make_absolute_path(cmd));
+		cmd_path = cmd;
 		cmd = slash;
 	}
 
@@ -451,16 +426,12 @@ int main(int argc, const char **argv)
 	cmd = argv[0];
 
 	/*
-	 * We execute external git command via execv_git_cmd(),
-	 * which looks at "--exec-path" option, GIT_EXEC_PATH
-	 * environment, and $(gitexecdir) in Makefile while built,
-	 * in this order.  For scripted commands, we prepend
-	 * the value of the exec_path variable to the PATH.
+	 * We use PATH to find git commands, but we prepend some higher
+	 * precidence paths: the "--exec-path" option, the GIT_EXEC_PATH
+	 * environment, and the $(gitexecdir) from the Makefile at build
+	 * time.
 	 */
-	if (exec_path)
-		prepend_to_path(exec_path, strlen(exec_path));
-	exec_path = git_exec_path();
-	prepend_to_path(exec_path, strlen(exec_path));
+	setup_path(cmd_path);
 
 	while (1) {
 		/* See if it's an internal command */
-- 
gitgui.0.8.4.11176.gd9205-dirty

^ permalink raw reply related

* (unknown)
From: racin @ 2007-10-22 18:16 UTC (permalink / raw)
  To: git


Hello,

I found the following on the development version of git.el: saving
non-git-managed files in Emacs threw an error.

It is due to a simple error in the call to condition-case in a
recently added function, git-update-save-file.

I attached the patch for your convenience.

Regards,
Matthieu Lemerre

PS: Please Cc me when you ackwowledge; I'm not subscribed to the list.
As a matter of fact, I found the bug only because I didn't find git.el
for my distribution (debian) so I got directly from the development
version on the website.

^ permalink raw reply

* [PATCH, take 2] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 17:29 UTC (permalink / raw)
  To: Git Mailing List, Junio C Hamano, Shawn O. Pearce
  Cc: David Kastrup, Jeff King, Sven Verdoolaege
In-Reply-To: <alpine.LFD.0.999.0710220932150.10525@woody.linux-foundation.org>


Ok, as some people notices, there were a few bugs in the previous patch. I 
didn't free the hashes correctly (stupid) and the Makefile had "hash.o" 
instead of "hash.h".

But more importantly, my "testing" had been totally broken, because I had 
forgotten to actually move the rename limiting code to after the exact 
rename phase, so when I tested the 100,000 file rename, almost none of the 
new code triggered, so my performance testing was totally bogus.

When fixing that, I noticed that while my new exact rename detection was 
essentially instantaneous, there were some O(n*m) effects in the generic 
diff code from the extremely stupid way we handled the "was it a copy or a 
rename" issue.

To fix that, I just made the "was the path used by a rename" be a counter 
instead of a single "it was used"

With that in place, I could actually time the rename detection of 100,000 
files in my big-rename test repository. This is what it looks like when 
you rename a hundred thousand files:

	[torvalds@woody big-rename]$ time ~/git/git show -C | wc -l
	400006

	real    0m2.675s
	user    0m2.148s
	sys     0m0.540s

(each renamed file is 4 lines: they looks like

	diff --git a/really-big-dir/file-1-1-1-1-1 b/moved-big-dir/file-1-1-1-1-1
	similarity index 100%
	rename from really-big-dir/file-1-1-1-1-1
	rename to moved-big-dir/file-1-1-1-1-1

and the extra six lines is from a one-liner commit message and all the 
commit information and spacing).

So two seconds to do that exact rename detection.

Now, I can't really compare it to the "before" stage, because that is just 
so horrible. The rename detection limit triggers, so you never even get 
any renames, but if I were to move the limit check later (like I do in 
this patch) without my other fixes, it would take hours. Trying to do ten 
billion (100k x 100k) SHA1 and pathname compares simply isn't going to 
work.

But I *can* compare it to the old code *with* the rename limiting, which 
still wastes all the time on the whole "copy usage" crap. So here are the 
numbers on that repo without the patch:

	[torvalds@woody big-rename]$ time git show -C | wc -l
	1400006
	
	real    0m12.383s
	user    0m12.365s
	sys     0m0.160s

That's right: we used to take 12 seconds and not even do renames (now you 
see fourteen lines per file moved: seven lines each for the delete and the 
create of a one-liner file, and the same extra six lines of commit 
information).

So it not only makes the rename detection possible in the first place, it 
removes some stupid code that made it take a long time even when it 
failed!

Now, I'd still be careful with this patch, and I'd really like people to 
double-check all my logic, but I think it's worthy of some 'pu' love.

		Linus
---

 Makefile          |    4 +-
 diff.c            |   24 +----
 diffcore-rename.c |  275 ++++++++++++++++++++++++++++++----------------------
 diffcore.h        |    2 +-
 hash.c            |  110 +++++++++++++++++++++
 hash.h            |   43 ++++++++
 6 files changed, 321 insertions(+), 137 deletions(-)

diff --git a/Makefile b/Makefile
index 8db4dbe..b1ca186 100644
--- a/Makefile
+++ b/Makefile
@@ -291,7 +291,7 @@ LIB_H = \
 	run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
 	tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h builtin.h \
 	utf8.h reflog-walk.h patch-ids.h attr.h decorate.h progress.h \
-	mailmap.h remote.h
+	mailmap.h remote.h hash.h
 
 DIFF_OBJS = \
 	diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@@ -301,7 +301,7 @@ DIFF_OBJS = \
 LIB_OBJS = \
 	blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \
 	date.o diff-delta.o entry.o exec_cmd.o ident.o \
-	interpolate.o \
+	interpolate.o hash.o \
 	lockfile.o \
 	patch-ids.o \
 	object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \
diff --git a/diff.c b/diff.c
index 6648e01..e892030 100644
--- a/diff.c
+++ b/diff.c
@@ -2586,9 +2586,9 @@ void diff_debug_filepair(const struct diff_filepair *p, int i)
 {
 	diff_debug_filespec(p->one, i, "one");
 	diff_debug_filespec(p->two, i, "two");
-	fprintf(stderr, "score %d, status %c stays %d broken %d\n",
+	fprintf(stderr, "score %d, status %c rename_used %d broken %d\n",
 		p->score, p->status ? p->status : '?',
-		p->source_stays, p->broken_pair);
+		p->rename_used, p->broken_pair);
 }
 
 void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
@@ -2606,8 +2606,8 @@ void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
 
 static void diff_resolve_rename_copy(void)
 {
-	int i, j;
-	struct diff_filepair *p, *pp;
+	int i;
+	struct diff_filepair *p;
 	struct diff_queue_struct *q = &diff_queued_diff;
 
 	diff_debug_queue("resolve-rename-copy", q);
@@ -2629,27 +2629,15 @@ static void diff_resolve_rename_copy(void)
 		 * either in-place edit or rename/copy edit.
 		 */
 		else if (DIFF_PAIR_RENAME(p)) {
-			if (p->source_stays) {
-				p->status = DIFF_STATUS_COPIED;
-				continue;
-			}
 			/* See if there is some other filepair that
 			 * copies from the same source as us.  If so
 			 * we are a copy.  Otherwise we are either a
 			 * copy if the path stays, or a rename if it
 			 * does not, but we already handled "stays" case.
 			 */
-			for (j = i + 1; j < q->nr; j++) {
-				pp = q->queue[j];
-				if (strcmp(pp->one->path, p->one->path))
-					continue; /* not us */
-				if (!DIFF_PAIR_RENAME(pp))
-					continue; /* not a rename/copy */
-				/* pp is a rename/copy from the same source */
+			if (--p->one->rename_used > 0)
 				p->status = DIFF_STATUS_COPIED;
-				break;
-			}
-			if (!p->status)
+			else
 				p->status = DIFF_STATUS_RENAMED;
 		}
 		else if (hashcmp(p->one->sha1, p->two->sha1) ||
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 2077a9b..cc105db 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -4,6 +4,7 @@
 #include "cache.h"
 #include "diff.h"
 #include "diffcore.h"
+#include "hash.h"
 
 /* Table of rename/copy destinations */
 
@@ -55,12 +56,10 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
 static struct diff_rename_src {
 	struct diff_filespec *one;
 	unsigned short score; /* to remember the break score */
-	unsigned src_path_left : 1;
 } *rename_src;
 static int rename_src_nr, rename_src_alloc;
 
 static struct diff_rename_src *register_rename_src(struct diff_filespec *one,
-						   int src_path_left,
 						   unsigned short score)
 {
 	int first, last;
@@ -92,33 +91,9 @@ static struct diff_rename_src *register_rename_src(struct diff_filespec *one,
 			(rename_src_nr - first - 1) * sizeof(*rename_src));
 	rename_src[first].one = one;
 	rename_src[first].score = score;
-	rename_src[first].src_path_left = src_path_left;
 	return &(rename_src[first]);
 }
 
-static int is_exact_match(struct diff_filespec *src,
-			  struct diff_filespec *dst,
-			  int contents_too)
-{
-	if (src->sha1_valid && dst->sha1_valid &&
-	    !hashcmp(src->sha1, dst->sha1))
-		return 1;
-	if (!contents_too)
-		return 0;
-	if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1))
-		return 0;
-	if (src->size != dst->size)
-		return 0;
-	if (src->sha1_valid && dst->sha1_valid)
-	    return !hashcmp(src->sha1, dst->sha1);
-	if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
-		return 0;
-	if (src->size == dst->size &&
-	    !memcmp(src->data, dst->data, src->size))
-		return 1;
-	return 0;
-}
-
 static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)
 {
 	int src_len = strlen(src->path), dst_len = strlen(dst->path);
@@ -216,6 +191,7 @@ static void record_rename_pair(int dst_index, int src_index, int score)
 		die("internal error: dst already matched.");
 
 	src = rename_src[src_index].one;
+	src->rename_used++;
 	one = alloc_filespec(src->path);
 	fill_filespec(one, src->sha1, src->mode);
 
@@ -229,7 +205,6 @@ static void record_rename_pair(int dst_index, int src_index, int score)
 		dp->score = rename_src[src_index].score;
 	else
 		dp->score = score;
-	dp->source_stays = rename_src[src_index].src_path_left;
 	rename_dst[dst_index].pair = dp;
 }
 
@@ -247,19 +222,127 @@ static int score_compare(const void *a_, const void *b_)
 	return b->score - a->score;
 }
 
-static int compute_stays(struct diff_queue_struct *q,
-			 struct diff_filespec *one)
+struct file_similarity {
+	int src_dst, index;
+	struct diff_filespec *filespec;
+	struct file_similarity *next;
+};
+
+static int find_identical_files(struct file_similarity *src,
+				struct file_similarity *dst)
 {
-	int i;
-	for (i = 0; i < q->nr; i++) {
-		struct diff_filepair *p = q->queue[i];
-		if (strcmp(one->path, p->two->path))
-			continue;
-		if (DIFF_PAIR_RENAME(p)) {
-			return 0; /* something else is renamed into this */
+	int renames = 0;
+	do {
+		struct diff_filespec *one = src->filespec;
+		struct file_similarity *p, *best;
+		int i = 100;
+
+		best = NULL;
+		for (p = dst; p; p = p->next) {
+			struct diff_filespec *two = p->filespec;
+
+			/* Already picked as a destination? */
+			if (!p->src_dst)
+				continue;
+			/* False hash collission? */
+			if (hashcmp(one->sha1, two->sha1))
+				continue;
+			best = p;
+			if (basename_same(one, two))
+				break;
+
+			/* Too many identical alternatives? Pick one */
+			if (!--i)
+				break;
 		}
+		if (best) {
+			best->src_dst = 0;
+			record_rename_pair(best->index, src->index, MAX_SCORE);
+			renames++;
+		}
+	} while ((src = src->next) != NULL);
+	return renames;
+}
+
+/*
+ * Note: the rest of the rename logic depends on this
+ * phase also populating all the filespecs for any
+ * entry that isn't matched up with an exact rename.
+ */
+static void free_similarity_list(struct file_similarity *p)
+{
+	while (p) {
+		struct file_similarity *entry = p;
+		p = p->next;
+
+		/* Stupid special case, see note above! */
+		diff_populate_filespec(entry->filespec, 0);
+		free(entry);
+	}
+}
+
+static int find_same_files(void *ptr)
+{
+	int ret;
+	struct file_similarity *p = ptr;
+	struct file_similarity *src = NULL, *dst = NULL;
+
+	/* Split the hash list up into sources and destinations */
+	do {
+		struct file_similarity *entry = p;
+		p = p->next;
+		if (entry->src_dst < 0) {
+			entry->next = src;
+			src = entry;
+		} else {
+			entry->next = dst;
+			dst = entry;
+		}
+	} while (p);
+
+	/*
+	 * If we have both sources *and* destinations, see if
+	 * we can match them up
+	 */
+	ret = (src && dst) ? find_identical_files(src, dst) : 0;
+
+	/* Free the hashes and return the number of renames found */
+	free_similarity_list(src);
+	free_similarity_list(dst);
+	return ret;
+}
+
+static unsigned int hash_filespec(struct diff_filespec *filespec)
+{
+	unsigned int hash;
+	if (!filespec->sha1_valid) {
+		if (diff_populate_filespec(filespec, 0))
+			return 0;
+		hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1);
+	}
+	memcpy(&hash, filespec->sha1, sizeof(hash));
+	return hash;
+}
+
+static void insert_file_table(struct hash_table *table, int src_dst, int index, struct diff_filespec *filespec)
+{
+	void **pos;
+	unsigned int hash;
+	struct file_similarity *entry = xmalloc(sizeof(*entry));
+
+	entry->src_dst = src_dst;
+	entry->index = index;
+	entry->filespec = filespec;
+	entry->next = NULL;
+
+	hash = hash_filespec(filespec);
+	pos = insert_hash(hash, entry, table);
+
+	/* We already had an entry there? */
+	if (pos) {
+		entry->next = *pos;
+		*pos = entry;
 	}
-	return 1;
 }
 
 /*
@@ -268,50 +351,26 @@ static int compute_stays(struct diff_queue_struct *q,
  * The first round matches up the up-to-date entries,
  * and then during the second round we try to match
  * cache-dirty entries as well.
- *
- * Note: the rest of the rename logic depends on this
- * phase also populating all the filespecs for any
- * entry that isn't matched up with an exact rename,
- * see "is_exact_match()".
  */
 static int find_exact_renames(void)
 {
-	int rename_count = 0;
-	int contents_too;
-
-	for (contents_too = 0; contents_too < 2; contents_too++) {
-		int i;
-
-		for (i = 0; i < rename_dst_nr; i++) {
-			struct diff_filespec *two = rename_dst[i].two;
-			int j;
-
-			if (rename_dst[i].pair)
-				continue; /* dealt with an earlier round */
-			for (j = 0; j < rename_src_nr; j++) {
-				int k;
-				struct diff_filespec *one = rename_src[j].one;
-				if (!is_exact_match(one, two, contents_too))
-					continue;
-
-				/* see if there is a basename match, too */
-				for (k = j; k < rename_src_nr; k++) {
-					one = rename_src[k].one;
-					if (basename_same(one, two) &&
-						is_exact_match(one, two,
-							contents_too)) {
-						j = k;
-						break;
-					}
-				}
-
-				record_rename_pair(i, j, (int)MAX_SCORE);
-				rename_count++;
-				break; /* we are done with this entry */
-			}
-		}
-	}
-	return rename_count;
+	int i;
+	struct hash_table file_table;
+
+	init_hash(&file_table);
+	for (i = 0; i < rename_src_nr; i++)
+		insert_file_table(&file_table, -1, i, rename_src[i].one);
+
+	for (i = 0; i < rename_dst_nr; i++)
+		insert_file_table(&file_table, 1, i, rename_dst[i].two);
+
+	/* Find the renames */
+	i = for_each_hash(&file_table, find_same_files);
+
+	/* .. and free the hash data structure */
+	free_hash(&file_table);
+
+	return i;
 }
 
 void diffcore_rename(struct diff_options *options)
@@ -340,20 +399,36 @@ void diffcore_rename(struct diff_options *options)
 				locate_rename_dst(p->two, 1);
 		}
 		else if (!DIFF_FILE_VALID(p->two)) {
-			/* If the source is a broken "delete", and
+			/*
+			 * If the source is a broken "delete", and
 			 * they did not really want to get broken,
 			 * that means the source actually stays.
+			 * So we increment the "rename_used" score
+			 * by one, to indicate ourselves as a user
 			 */
-			int stays = (p->broken_pair && !p->score);
-			register_rename_src(p->one, stays, p->score);
+			if (p->broken_pair && !p->score)
+				p->one->rename_used++;
+			register_rename_src(p->one, p->score);
+		}
+		else if (detect_rename == DIFF_DETECT_COPY) {
+			/*
+			 * Increment the "rename_used" score by
+			 * one, to indicate ourselves as a user.
+			 */
+			p->one->rename_used++;
+			register_rename_src(p->one, p->score);
 		}
-		else if (detect_rename == DIFF_DETECT_COPY)
-			register_rename_src(p->one, 1, p->score);
 	}
 	if (rename_dst_nr == 0 || rename_src_nr == 0)
 		goto cleanup; /* nothing to do */
 
 	/*
+	 * We really want to cull the candidates list early
+	 * with cheap tests in order to avoid doing deltas.
+	 */
+	rename_count = find_exact_renames();
+
+	/*
 	 * This basically does a test for the rename matrix not
 	 * growing larger than a "rename_limit" square matrix, ie:
 	 *
@@ -369,12 +444,6 @@ void diffcore_rename(struct diff_options *options)
 	if (rename_dst_nr * rename_src_nr > rename_limit * rename_limit)
 		goto cleanup;
 
-	/*
-	 * We really want to cull the candidates list early
-	 * with cheap tests in order to avoid doing deltas.
-	 */
-	rename_count = find_exact_renames();
-
 	/* Have we run out the created file pool?  If so we can avoid
 	 * doing the delta matrix altogether.
 	 */
@@ -474,16 +543,7 @@ void diffcore_rename(struct diff_options *options)
 					pair_to_free = p;
 			}
 			else {
-				for (j = 0; j < rename_dst_nr; j++) {
-					if (!rename_dst[j].pair)
-						continue;
-					if (strcmp(rename_dst[j].pair->
-						   one->path,
-						   p->one->path))
-						continue;
-					break;
-				}
-				if (j < rename_dst_nr)
+				if (p->one->rename_used)
 					/* this path remains */
 					pair_to_free = p;
 			}
@@ -509,23 +569,6 @@ void diffcore_rename(struct diff_options *options)
 	*q = outq;
 	diff_debug_queue("done collapsing", q);
 
-	/* We need to see which rename source really stays here;
-	 * earlier we only checked if the path is left in the result,
-	 * but even if a path remains in the result, if that is coming
-	 * from copying something else on top of it, then the original
-	 * source is lost and does not stay.
-	 */
-	for (i = 0; i < q->nr; i++) {
-		struct diff_filepair *p = q->queue[i];
-		if (DIFF_PAIR_RENAME(p) && p->source_stays) {
-			/* If one appears as the target of a rename-copy,
-			 * then mark p->source_stays = 0; otherwise
-			 * leave it as is.
-			 */
-			p->source_stays = compute_stays(q, p->one);
-		}
-	}
-
 	for (i = 0; i < rename_dst_nr; i++) {
 		diff_free_filespec_data(rename_dst[i].two);
 		free(rename_dst[i].two);
diff --git a/diffcore.h b/diffcore.h
index eb618b1..ceda932 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -30,6 +30,7 @@ struct diff_filespec {
 	const char *funcname_pattern_ident;
 	unsigned long size;
 	int xfrm_flags;		 /* for use by the xfrm */
+	int rename_used;         /* Count of rename users */
 	unsigned short mode;	 /* file mode */
 	unsigned sha1_valid : 1; /* if true, use sha1 and trust mode;
 				  * if false, use the name and read from
@@ -56,7 +57,6 @@ struct diff_filepair {
 	struct diff_filespec *two;
 	unsigned short int score;
 	char status; /* M C R N D U (see Documentation/diff-format.txt) */
-	unsigned source_stays : 1; /* all of R/C are copies */
 	unsigned broken_pair : 1;
 	unsigned renamed_pair : 1;
 	unsigned is_unmerged : 1;
diff --git a/hash.c b/hash.c
new file mode 100644
index 0000000..7b492d4
--- /dev/null
+++ b/hash.c
@@ -0,0 +1,110 @@
+/*
+ * Some generic hashing helpers.
+ */
+#include "cache.h"
+#include "hash.h"
+
+/*
+ * Look up a hash entry in the hash table. Return the pointer to
+ * the existing entry, or the empty slot if none existed. The caller
+ * can then look at the (*ptr) to see whether it existed or not.
+ */
+static struct hash_table_entry *lookup_hash_entry(unsigned int hash, struct hash_table *table)
+{
+	unsigned int size = table->size, nr = hash % size;
+	struct hash_table_entry *array = table->array;
+
+	while (array[nr].ptr) {
+		if (array[nr].hash == hash)
+			break;
+		nr++;
+		if (nr >= size)
+			nr = 0;
+	}
+	return array + nr;
+}
+
+
+/*
+ * Insert a new hash entry pointer into the table.
+ *
+ * If that hash entry already existed, return the pointer to
+ * the existing entry (and the caller can create a list of the
+ * pointers or do anything else). If it didn't exist, return
+ * NULL (and the caller knows the pointer has been inserted).
+ */
+static void **insert_hash_entry(unsigned int hash, void *ptr, struct hash_table *table)
+{
+	struct hash_table_entry *entry = lookup_hash_entry(hash, table);
+
+	if (!entry->ptr) {
+		entry->ptr = ptr;
+		entry->hash = hash;
+		table->nr++;
+		return NULL;
+	}
+	return &entry->ptr;
+}
+
+static void grow_hash_table(struct hash_table *table)
+{
+	unsigned int i;
+	unsigned int old_size = table->size, new_size;
+	struct hash_table_entry *old_array = table->array, *new_array;
+
+	new_size = alloc_nr(old_size);
+	new_array = xcalloc(sizeof(struct hash_table_entry), new_size);
+	table->size = new_size;
+	table->array = new_array;
+	table->nr = 0;
+	for (i = 0; i < old_size; i++) {
+		unsigned int hash = old_array[i].hash;
+		void *ptr = old_array[i].ptr;
+		if (ptr)
+			insert_hash_entry(hash, ptr, table);
+	}
+	free(old_array);
+}
+
+void *lookup_hash(unsigned int hash, struct hash_table *table)
+{
+	if (!table->array)
+		return NULL;
+	return &lookup_hash_entry(hash, table)->ptr;
+}
+
+void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table)
+{
+	unsigned int nr = table->nr;
+	if (nr >= table->size/2)
+		grow_hash_table(table);
+	return insert_hash_entry(hash, ptr, table);
+}
+
+int for_each_hash(struct hash_table *table, int (*fn)(void *))
+{
+	int sum = 0;
+	unsigned int i;
+	unsigned int size = table->size;
+	struct hash_table_entry *array = table->array;
+
+	for (i = 0; i < size; i++) {
+		void *ptr = array->ptr;
+		array++;
+		if (ptr) {
+			int val = fn(ptr);
+			if (val < 0)
+				return val;
+			sum += val;
+		}
+	}
+	return sum;
+}
+
+void free_hash(struct hash_table *table)
+{
+	free(table->array);
+	table->array = NULL;
+	table->size = 0;
+	table->nr = 0;
+}
diff --git a/hash.h b/hash.h
new file mode 100644
index 0000000..5056c9a
--- /dev/null
+++ b/hash.h
@@ -0,0 +1,43 @@
+#ifndef HASH_H
+#define HASH_H
+
+/*
+ * These are some simple generic hash table helper functions.
+ * Not necessarily suitable for all users, but good for things
+ * where you want to just keep track of a list of things, and
+ * have a good hash to use on them.
+ *
+ * It keeps the hash table at roughly 50-75% free, so the memory
+ * cost of the hash table itself is roughly
+ *
+ *	3 * 2*sizeof(void *) * nr_of_objects
+ *
+ * bytes. 
+ *
+ * FIXME: on 64-bit architectures, we waste memory. It would be
+ * good to have just 32-bit pointers, requiring a special allocator
+ * for hashed entries or something.
+ */
+struct hash_table_entry {
+	unsigned int hash;
+	void *ptr;
+};
+
+struct hash_table {
+	unsigned int size, nr;
+	struct hash_table_entry *array;
+};
+
+extern void *lookup_hash(unsigned int hash, struct hash_table *table);
+extern void **insert_hash(unsigned int hash, void *ptr, struct hash_table *table);
+extern int for_each_hash(struct hash_table *table, int (*fn)(void *));
+extern void free_hash(struct hash_table *table);
+
+static inline void init_hash(struct hash_table *table)
+{
+	table->size = 0;
+	table->nr = 0;
+	table->array = NULL;
+}
+
+#endif

^ permalink raw reply related

* Re: [PATCH] use only the PATH for exec'ing git commands
From: Johannes Schindelin @ 2007-10-22 17:44 UTC (permalink / raw)
  To: Scott R Parish; +Cc: git
In-Reply-To: <20071022170148.GB29642@srparish.net>

Hi,

On Mon, 22 Oct 2007, Scott R Parish wrote:

>  3 files changed, 61 insertions(+), 105 deletions(-)

Nice.

Ciao,
Dscho

^ permalink raw reply

* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Steffen Prohaska @ 2007-10-22 15:42 UTC (permalink / raw)
  To: Andreas Ericsson
  Cc: Johannes Schindelin, Jakub Narebski, Federico Mena Quintero, git
In-Reply-To: <471CBEB1.2030008@op5.se>


On Oct 22, 2007, at 5:16 PM, Andreas Ericsson wrote:

> Johannes Schindelin wrote:
>> Hi,
>> On Mon, 22 Oct 2007, Andreas Ericsson wrote:
>>> Johannes Schindelin wrote:
>>>
>>>> On Mon, 22 Oct 2007, Andreas Ericsson wrote:
>>>>
>>>>> If I were to suggest any improvements, it'd be to change the  
>>>>> semantics of git-pull to always update the local branches set  
>>>>> up to be merged with the remote tracking branches when they,  
>>>>> prior to fetching, pointed to the same commit, such that when
>>>>>
>>>>> $ git show-ref master
>>>>> d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/heads/master
>>>>> d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/remotes/origin/ 
>>>>> master
>>>>>
>>>>> refs/heads/master gets set to refs/remotes/origin/master post- 
>>>>> fetch.
>>>> In general, this should fail.  Because you are expected to have  
>>>> local changes in the local branches.
>>>
>>> BS argument.
>> Aha.  So you want to make sure that the local branches are no  
>> longer "purely" local.  And you want to stop updating them when  
>> unpushed changes are in the local branches.
>
> To me, it's more along the lines of "let git help me not make the  
> mistake of hacking on a six-week old codebase when I've explicitly  
> asked it to merge these and those remote tracking branches into  
> these and those local branches". Not updating those branches when  
> there *are* changes on them is something users can understand and  
> will probably also appreciate, but the reason for not allowing even  
> fast-forwards escape me.

Here's also an interesting asymmetry. By default, git push
updates all remote branches matching a local branch. But git
pull "updates" only the current local branch to the state of
the remote head (by updating all local copies of the remote
branches, but merging only a single of these heads).

Maybe this asymmetry adds to the confusion. I see arguments
for both behaviours:
1) In both cases, update only the branch you're on
or
2) in both cases update all matching branches.
(btw, if I do not intend to merge at all, you can always use
"git fetch".)

	Steffen

^ permalink raw reply

* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Robin Rosenberg @ 2007-10-22 17:48 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Wincent Colaiuta, Andreas Ericsson, Jakub Narebski,
	Steffen Prohaska, Federico Mena Quintero, git
In-Reply-To: <Pine.LNX.4.64.0710221428390.25221@racer.site>


My list

     61 show
     35 gitk
     31 diff
     23 fetch
     12 reset
     12 blame
     11 clone
     11 checkout
     10 remote
     10 rebase
      9 status
      5 commit
      4 branch
      3 clean
      2 revert
      2 merge
      2 ls-remote
      2 gui

-- robin

^ permalink raw reply

* Re: [PATCH] Dissociating a repository from its alternates
From: Michael Hendricks @ 2007-10-22 18:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, git
In-Reply-To: <7v8xex50aa.fsf@assigned-by-dhcp.cox.net>

On Fri, Feb 16, 2007 at 12:13:01PM -0800, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > On Wed, 14 Feb 2007, Junio C Hamano wrote:
> >
> >> People often start out with "clone -l -s" (or --reference) and
> >> later wish to dissociate the repository from its alternates.
> >
> > Why not make a really dumb script which just _copies_ (or maybe 
> > optionally hard link) the objects from the alternate repo, and then kills 
> > the alternatives file? That should be easier. You always can repack after 
> > that.
> 
> I think that is much safer.

Was such a script ever incorporated into Git?

-- 
Michael

^ permalink raw reply

* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Daniel Barkalow @ 2007-10-22 18:06 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Andreas Ericsson, Jakub Narebski, Steffen Prohaska,
	Federico Mena Quintero, git
In-Reply-To: <Pine.LNX.4.64.0710221445170.25221@racer.site>

On Mon, 22 Oct 2007, Johannes Schindelin wrote:

> Hi,
> 
> On Mon, 22 Oct 2007, Andreas Ericsson wrote:
> 
> > If I were to suggest any improvements, it'd be to change the semantics of
> > git-pull to always update the local branches set up to be merged with the
> > remote tracking branches when they, prior to fetching, pointed to the same
> > commit, such that when
> > 
> > $ git show-ref master
> > d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/heads/master
> > d4027a816dd0b416dc8c7b37e2c260e6905f11b6 refs/remotes/origin/master
> > 
> > refs/heads/master gets set to refs/remotes/origin/master post-fetch.
> 
> In general, this should fail.  Because you are expected to have local 
> changes in the local branches.  What you describe suggests that you should 
> not use the branch name "master" at all, but "origin/master".

If you push your changes to the origin soon after making them, you'll only 
have local changes if somebody else changed something while you were 
working on a change. You're expected to create local changes in the local 
branches, but you shouldn't generally sit on them forever, and when you've 
pushed them, you no longer have any difference in content between local 
and remote.

If the project has multiple branches in the central repository, and you 
make changes for each of them at different times, but only one each day, 
the normal case will be to have local changes sitting in at most one of 
the branches, and, in particular, no local changes left in any branch 
other than HEAD.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [PATCH] use only the PATH for exec'ing git commands
From: Alex Riesen @ 2007-10-22 19:01 UTC (permalink / raw)
  To: Scott R Parish; +Cc: git
In-Reply-To: <20071022170148.GB29642@srparish.net>

Scott R Parish, Mon, Oct 22, 2007 19:01:48 +0200:
> +static void add_path(struct strbuf *out, const char *path)
> +{
> +	if (path && strlen(path)) {
> +		if (is_absolute_path(path))
> +			strbuf_addstr(out, path);
> +		else
> +			strbuf_addstr(out, make_absolute_path(path));
> +
> +		strbuf_addch(out, ':');

Shouldn't it break MingW32 native port?

> +	}
> +}
> +
> +void setup_path(const char *cmd_path)
> +{
> +	const char *old_path = getenv("PATH");
> +	struct strbuf new_path;
> +
> +	strbuf_init(&new_path, 0);
> +
> +	add_path(&new_path, argv_exec_path);
> +	add_path(&new_path, getenv(EXEC_PATH_ENVIRONMENT));
> +	add_path(&new_path, builtin_exec_path);
> +	add_path(&new_path, cmd_path);
> +		

trailing space

> +	if (old_path)
> +		strbuf_addstr(&new_path, old_path);
> +	else 
> +		strbuf_addstr(&new_path, "/usr/local/bin:/usr/bin:/bin");

the default PATH is platform-dependent. Git is multi-platform.
You should consider putting the path list somewhere in Makefile,
config.mak or configure.

> +
> +	setenv("PATH", new_path.buf, 1);

^ permalink raw reply

* Re: [PATCH] Dissociating a repository from its alternates
From: Johannes Schindelin @ 2007-10-22 19:05 UTC (permalink / raw)
  To: Michael Hendricks; +Cc: Junio C Hamano, git
In-Reply-To: <20071022180424.GA17429@ginosko.local>

Hi,

On Mon, 22 Oct 2007, Michael Hendricks wrote:

> On Fri, Feb 16, 2007 at 12:13:01PM -0800, Junio C Hamano wrote:
> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> > 
> > > On Wed, 14 Feb 2007, Junio C Hamano wrote:
> > >
> > >> People often start out with "clone -l -s" (or --reference) and
> > >> later wish to dissociate the repository from its alternates.
> > >
> > > Why not make a really dumb script which just _copies_ (or maybe 
> > > optionally hard link) the objects from the alternate repo, and then kills 
> > > the alternatives file? That should be easier. You always can repack after 
> > > that.
> > 
> > I think that is much safer.
> 
> Was such a script ever incorporated into Git?

Not that I know of, but "git repack -a && rm .git/objects/info/alternates" 
should do what you want.  You can even make a script of it, add some 
documentation and a test case, and earn git fame by posting a patch ;-)

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] use only the PATH for exec'ing git commands
From: Eric Merritt @ 2007-10-22 19:25 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Scott R Parish, git
In-Reply-To: <20071022190102.GA23714@steel.home>

> the default PATH is platform-dependent. Git is multi-platform.
> You should consider putting the path list somewhere in Makefile,
> config.mak or configure.

This static configuration that you describe is one of the things this
patch is designed to strip out. Compile time configuration breaks down
completly if you don't deploy to the path defined when the system was
compiled. Thats a problem.

^ permalink raw reply

* Re: [PATCH, take 2] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 19:31 UTC (permalink / raw)
  To: Git Mailing List, Junio C Hamano, Shawn O. Pearce
  Cc: David Kastrup, Jeff King, Sven Verdoolaege
In-Reply-To: <alpine.LFD.0.999.0710221009580.10525@woody.linux-foundation.org>



On Mon, 22 Oct 2007, Linus Torvalds wrote:
> 
> Ok, as some people notices, there were a few bugs in the previous patch. I 
> didn't free the hashes correctly (stupid) and the Makefile had "hash.o" 
> instead of "hash.h".

Ok, there were still more bugs, and before you get too involved with this 
last patch (not that I've seen any comments yet), apply this appended 
patch to actually fix things a bit more first!

Yes, I'm a moron. I hadn't even bothered to run the test-suite on it, and 
that showed several silly problems.

One of the problems was that since the rename detection copied the 
diffspecs around, the "rename_used" count couldn't work right, because 
things got copied around and the count stayed with one diffspec, but not 
the other..

In the kernel, we have a rule that says that any data structure that isn't 
ref-counted is basically a bug, and that was true here too. Instead of 
copying and splitting the diffspecs, just refcount them and keep track of 
how many users there are.

While the above bug was a somewhat subtle issue from me trying to be 
clever in avoiding the O(n*m) file copy/rename reuse issue, there were a 
few issues that were me just being totally braindead: the exact rename 
detection had lost the code that took file modes into account, so it would 
generate "renames" from regular files to symlinks, that the generic diff 
core layer would just split up again.

And even more stupidly, I had matched up the src/dst things when finding 
the rename, which just complicated things (added a totally unnecessary 
need to keep track of a destination being used more than once) and also 
broke the basename matching comparison. Duh.

So here's an incremental patch on top of the previous failed try. And if 
somebody is confused (and that might be me) and cannot get things to 
apply, just holler and I'll send the whole thing again. I might even try 
to clean up the series a bit and do it in stages.

This patch shouldn't change any performance behaviour (well, it might 
speed things up a bit to not allocate those diffspec structures, but it's 
unlikely that is even measurable). It just fixes stuff.

I'm sure there's more to come..

		Linus

---
 diff.c            |   17 ++++++++++++-----
 diffcore-rename.c |   40 ++++++++++++++++++++++------------------
 diffcore.h        |    2 ++
 3 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/diff.c b/diff.c
index e892030..2e74cb3 100644
--- a/diff.c
+++ b/diff.c
@@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path)
 	memset(spec, 0, sizeof(*spec));
 	spec->path = (char *)(spec + 1);
 	memcpy(spec->path, path, namelen+1);
+	spec->count = 1;
 	return spec;
 }
 
+void free_filespec(struct diff_filespec *spec)
+{
+	if (!--spec->count) {
+		diff_free_filespec_data(spec);
+		free(spec);
+	}
+}
+
 void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
 		   unsigned short mode)
 {
@@ -2431,10 +2440,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
 
 void diff_free_filepair(struct diff_filepair *p)
 {
-	diff_free_filespec_data(p->one);
-	diff_free_filespec_data(p->two);
-	free(p->one);
-	free(p->two);
+	free_filespec(p->one);
+	free_filespec(p->two);
 	free(p);
 }
 
@@ -2588,7 +2595,7 @@ void diff_debug_filepair(const struct diff_filepair *p, int i)
 	diff_debug_filespec(p->two, i, "two");
 	fprintf(stderr, "score %d, status %c rename_used %d broken %d\n",
 		p->score, p->status ? p->status : '?',
-		p->rename_used, p->broken_pair);
+		p->one->rename_used, p->broken_pair);
 }
 
 void diff_debug_queue(const char *msg, struct diff_queue_struct *q)
diff --git a/diffcore-rename.c b/diffcore-rename.c
index cc105db..3946932 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -184,7 +184,7 @@ static int estimate_similarity(struct diff_filespec *src,
 
 static void record_rename_pair(int dst_index, int src_index, int score)
 {
-	struct diff_filespec *one, *two, *src, *dst;
+	struct diff_filespec *src, *dst;
 	struct diff_filepair *dp;
 
 	if (rename_dst[dst_index].pair)
@@ -192,14 +192,12 @@ static void record_rename_pair(int dst_index, int src_index, int score)
 
 	src = rename_src[src_index].one;
 	src->rename_used++;
-	one = alloc_filespec(src->path);
-	fill_filespec(one, src->sha1, src->mode);
+	src->count++;
 
 	dst = rename_dst[dst_index].two;
-	two = alloc_filespec(dst->path);
-	fill_filespec(two, dst->sha1, dst->mode);
+	dst->count++;
 
-	dp = diff_queue(NULL, one, two);
+	dp = diff_queue(NULL, src, dst);
 	dp->renamed_pair = 1;
 	if (!strcmp(src->path, dst->path))
 		dp->score = rename_src[src_index].score;
@@ -232,21 +230,30 @@ static int find_identical_files(struct file_similarity *src,
 				struct file_similarity *dst)
 {
 	int renames = 0;
+
+	/*
+	 * Walk over all the destinations ...
+	 */
 	do {
-		struct diff_filespec *one = src->filespec;
+		struct diff_filespec *one = dst->filespec;
 		struct file_similarity *p, *best;
 		int i = 100;
 
+		/*
+		 * .. to find the best source match
+		 */
 		best = NULL;
-		for (p = dst; p; p = p->next) {
+		for (p = src; p; p = p->next) {
 			struct diff_filespec *two = p->filespec;
 
-			/* Already picked as a destination? */
-			if (!p->src_dst)
-				continue;
 			/* False hash collission? */
 			if (hashcmp(one->sha1, two->sha1))
 				continue;
+			/* Non-regular files? If so, the modes must match! */
+			if (!S_ISREG(one->mode) || !S_ISREG(two->mode)) {
+				if (one->mode != two->mode)
+					continue;
+			}
 			best = p;
 			if (basename_same(one, two))
 				break;
@@ -256,11 +263,10 @@ static int find_identical_files(struct file_similarity *src,
 				break;
 		}
 		if (best) {
-			best->src_dst = 0;
-			record_rename_pair(best->index, src->index, MAX_SCORE);
+			record_rename_pair(dst->index, best->index, MAX_SCORE);
 			renames++;
 		}
-	} while ((src = src->next) != NULL);
+	} while ((dst = dst->next) != NULL);
 	return renames;
 }
 
@@ -569,10 +575,8 @@ void diffcore_rename(struct diff_options *options)
 	*q = outq;
 	diff_debug_queue("done collapsing", q);
 
-	for (i = 0; i < rename_dst_nr; i++) {
-		diff_free_filespec_data(rename_dst[i].two);
-		free(rename_dst[i].two);
-	}
+	for (i = 0; i < rename_dst_nr; i++)
+		free_filespec(rename_dst[i].two);
 
 	free(rename_dst);
 	rename_dst = NULL;
diff --git a/diffcore.h b/diffcore.h
index ceda932..cc96c20 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -29,6 +29,7 @@ struct diff_filespec {
 	void *cnt_data;
 	const char *funcname_pattern_ident;
 	unsigned long size;
+	int count;               /* Reference count */
 	int xfrm_flags;		 /* for use by the xfrm */
 	int rename_used;         /* Count of rename users */
 	unsigned short mode;	 /* file mode */
@@ -44,6 +45,7 @@ struct diff_filespec {
 };
 
 extern struct diff_filespec *alloc_filespec(const char *);
+extern void free_filespec(struct diff_filespec *);
 extern void fill_filespec(struct diff_filespec *, const unsigned char *,
 			  unsigned short);
 

^ permalink raw reply related

* Re: best git practices, was Re: Git User's Survey 2007 unfinished summary continued
From: Federico Mena Quintero @ 2007-10-22 19:36 UTC (permalink / raw)
  To: Andreas Ericsson; +Cc: Johannes Schindelin, git
In-Reply-To: <471CBEB1.2030008@op5.se>

On Mon, 2007-10-22 at 17:16 +0200, Andreas Ericsson wrote:

> To me, it's more along the lines of "let git help me not make the 
> mistake of hacking on a six-week old codebase when I've explicitly asked 
> it to merge these and those remote tracking branches into these and 
> those local branches". Not updating those branches when there *are* 
> changes on them is something users can understand and will probably also 
> appreciate, but the reason for not allowing even fast-forwards escape me.

I'd love this behavior, FWIW.

The "branches should not track their origin by default" seems suited
only to Linux kernel maintainers who frequently pull from many different
people, not to "random hacker who wants to keep track of a project he
doesn't maintain" :)

  Federico

^ permalink raw reply

* Re: [PATCH, take 2] Linear-time/space rename logic (exact renames only)
From: Linus Torvalds @ 2007-10-22 19:44 UTC (permalink / raw)
  To: Git Mailing List, Junio C Hamano, Shawn O. Pearce
  Cc: David Kastrup, Jeff King, Sven Verdoolaege
In-Reply-To: <alpine.LFD.0.999.0710221207300.30120@woody.linux-foundation.org>



On Mon, 22 Oct 2007, Linus Torvalds wrote:
> 
> I'm sure there's more to come..

One more detail.. The updated comment explains the issue: if we broke a 
file apart, and rename detection joined it back together, the result is 
neither a rename nor a copy, it's a regular modification (and all 
remaining renames will be copies of the original, so don't bother 
decrementing the "rename_used" count).

		Linus

---
 diff.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/diff.c b/diff.c
index 2e74cb3..e839f59 100644
--- a/diff.c
+++ b/diff.c
@@ -2636,13 +2636,19 @@ static void diff_resolve_rename_copy(void)
 		 * either in-place edit or rename/copy edit.
 		 */
 		else if (DIFF_PAIR_RENAME(p)) {
-			/* See if there is some other filepair that
-			 * copies from the same source as us.  If so
-			 * we are a copy.  Otherwise we are either a
-			 * copy if the path stays, or a rename if it
-			 * does not, but we already handled "stays" case.
+			/*
+			 * A rename might have re-connected a broken
+			 * pair up, causing the pathnames to be the
+			 * same again. If so, that's not a rename at
+			 * all, just a modification..
+			 *
+			 * Otherwise, see if this source was used for
+			 * multiple renames, in which case we decrement
+			 * the count, and call it a copy.
 			 */
-			if (--p->one->rename_used > 0)
+			if (!strcmp(p->one->path, p->two->path))
+				p->status = DIFF_STATUS_MODIFIED;
+			else if (--p->one->rename_used > 0)
 				p->status = DIFF_STATUS_COPIED;
 			else
 				p->status = DIFF_STATUS_RENAMED;

^ permalink raw reply related

* Re: odd behavior with concurrent fetch/checkout
From: J. Bruce Fields @ 2007-10-22 19:46 UTC (permalink / raw)
  To: git
In-Reply-To: <20071022165125.GG583@fieldses.org>

On Mon, Oct 22, 2007 at 12:51:25PM -0400, J. Bruce Fields wrote:
> Just now I checked out a topic branch in my working repo:
> 
> 	git checkout server-xprt-switch
> 
> and while waiting for it to complete (I just started work and caches
> were all cold), I ran a
> 
> 	git fetch origin
> 
> in another window to update from Linus.  The git fetch gave a warning:
> 
> 	remote: Generating pack...
> 	remote: Counting objects: 7550
> 	remote: Done counting 12885 objects.
> 	remote: Result has 8400 objects.
> 	remote: Deltifying 8400 objects...
> 	remote:  100% (8400/8400) done
> 	Indexing 8400 objects...
> 	remote: Total 8400 (delta 7257), reused 5696 (delta 4586)
> 	 100% (8400/8400) done
> 	Resolving 7257 deltas...
> 	 100% (7257/7257) done
> 	* refs/remotes/origin/master: fast forward to branch 'master' of
> 	* git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
> 	  old..new: d85714d..55b70a0
> 	Cannot fetch into the current branch.

By the way, I should have said--this is with git version
1.5.3.4.208.gc990.

--b.

> 
> Why the warning?  Also, afterwards I was left with server-xprt-switch
> pointing to the tip of the branch I'd just switched from (another
> miscellaneous topic branch).  The working directory was in some
> completely different state--thanks to a quick reset --hard I don't know
> what it was.  Also, in the reflog for the checked-out branch:
> 
> 	commit bac1e7977eb4781e62cee7f1c7c3d13a9e5d8d74
> 	Reflog: server-xprt-switch@{0} (J. Bruce Fields <bfields@citi.umich.edu>)
> 	Reflog message: fetch origin: Undoing incorrectly fetched HEAD.
> 	Author: J. Bruce Fields <bfields@citi.umich.edu>
> 	Date:   Mon Oct 22 12:32:37 2007 -0400
> 	...
> 
> Why was a fetch into the remote fooling with HEAD or anything under
> refs/heads/?
> 
> --b.
> -
> 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

^ permalink raw reply

* Re: [PATCH] use only the PATH for exec'ing git commands
From: Scott R Parish @ 2007-10-22 19:59 UTC (permalink / raw)
  To: Alex Riesen, git


> Alex Reisen, Mon, Oct 22, 2007 12:01:
> > +                strbuf_addch(out, ':');
>
> Shouldn't it break MingW32 native port?
>

<snip>

> > +        if (old_path)
> > +                strbuf_addstr(&amp;new_path, old_path);
> > +        else
> > +                strbuf_addstr(&amp;new_path,
"/usr/local/bin:/usr/bin:/bin");
>
> the default PATH is platform-dependent. Git is multi-platform.
> You should consider putting the path list somewhere in Makefile,
> config.mak or configure.
>

The original code was already doing both of these things (see git.c's
prepend_to_path())

sRp

^ permalink raw reply

* Re: [PATCH] use only the PATH for exec'ing git commands
From: Scott R Parish @ 2007-10-22 19:59 UTC (permalink / raw)
  To: Alex Riesen, git


> Alex Reisen, Mon, Oct 22, 2007 12:01:
> > +                strbuf_addch(out, ':');
>
> Shouldn't it break MingW32 native port?
>

<snip>

> > +        if (old_path)
> > +                strbuf_addstr(&amp;new_path, old_path);
> > +        else
> > +                strbuf_addstr(&amp;new_path,
"/usr/local/bin:/usr/bin:/bin");
>
> the default PATH is platform-dependent. Git is multi-platform.
> You should consider putting the path list somewhere in Makefile,
> config.mak or configure.
>

The original code was already doing both of these things (see git.c's
prepend_to_path())

sRp

^ permalink raw reply

* [PATCH] More updates and corrections to the russian translation of git-gui
From: Alex Riesen @ 2007-10-22 20:28 UTC (permalink / raw)
  To: git; +Cc: Shawn O. Pearce, Kirill

In particular many screw-ups after po regeneration were fixed.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
 po/ru.po |  362 ++++++++++++++++++++++----------------------------------------
 1 files changed, 127 insertions(+), 235 deletions(-)

diff --git a/po/ru.po b/po/ru.po
index ed5b67a..b8e9447 100644
--- a/po/ru.po
+++ b/po/ru.po
@@ -8,8 +8,8 @@ msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2007-10-10 04:04-0400\n"
-"PO-Revision-Date: 2007-10-20 14:29-0500\n"
-"Last-Translator: Kirill <kirillathome@gmail.com>\n"
+"PO-Revision-Date: 2007-10-22 22:30-0200\n"
+"Last-Translator: Alex Riesen <raa.lkml@gmail.com>\n"
 "Language-Team: Russian Translation <git@vger.kernel.org>\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -21,9 +21,9 @@ msgid "git-gui: fatal error"
 msgstr "git-gui: критическая ошибка"
 
 #: git-gui.sh:595
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Invalid font specified in %s:"
-msgstr "В оболочке установлен неверный шрифт.%s:"
+msgstr "В %s установлен неверный шрифт:"
 
 #: git-gui.sh:620
 msgid "Main Font"
@@ -31,7 +31,7 @@ msgstr "Шрифт интерфейса"
 
 #: git-gui.sh:621
 msgid "Diff/Console Font"
-msgstr "Шрифт в консоли diff"
+msgstr "Шрифт консоли и изменений (diff)"
 
 #: git-gui.sh:635
 msgid "Cannot find git in PATH."
@@ -64,9 +64,8 @@ msgid "Git directory not found:"
 msgstr "Каталог Git не найден:"
 
 #: git-gui.sh:860
-#, fuzzy
 msgid "Cannot move to top of working directory:"
-msgstr "Каталог.git испорчен: "
+msgstr "Невозможно перейти к корню рабочего каталога репозитория: "
 
 #: git-gui.sh:867
 msgid "Cannot use funny .git directory:"
@@ -78,7 +77,7 @@ msgstr "Отсутствует рабочий каталог"
 
 #: git-gui.sh:1019
 msgid "Refreshing file status..."
-msgstr "Обновление состояния файлов проекта..."
+msgstr "Обновление информации о состоянии файлов..."
 
 #: git-gui.sh:1084
 msgid "Scanning for modified files ..."
@@ -94,7 +93,7 @@ msgstr "Не изменено"
 
 #: git-gui.sh:1527
 msgid "Modified, not staged"
-msgstr "Изменено, но не включено"
+msgstr "Изменено, не подготовлено"
 
 #: git-gui.sh:1528 git-gui.sh:1533
 msgid "Staged for commit"
@@ -105,7 +104,6 @@ msgid "Portions staged for commit"
 msgstr "Части, подготовленные для сохранения"
 
 #: git-gui.sh:1530 git-gui.sh:1535
-#, fuzzy
 msgid "Staged for commit, missing"
 msgstr "Подготовлено для сохранения, отсутствует"
 
@@ -123,7 +121,7 @@ msgstr "Подготовлено для удаления"
 
 #: git-gui.sh:1539
 msgid "Staged for removal, still present"
-msgstr "Подготовлено для удаления, но еще не удалено"
+msgstr "Подготовлено для удаления, еще не удалено"
 
 #: git-gui.sh:1541 git-gui.sh:1542 git-gui.sh:1543 git-gui.sh:1544
 msgid "Requires merge resolution"
@@ -157,7 +155,6 @@ msgid "Branch"
 msgstr "Ветвь"
 
 #: git-gui.sh:1794 lib/choose_rev.tcl:547
-#, fuzzy
 msgid "Commit@@noun"
 msgstr "Состояние"
 
@@ -166,18 +163,16 @@ msgid "Merge"
 msgstr "Объединить"
 
 #: git-gui.sh:1798 lib/choose_rev.tcl:556
-#, fuzzy
 msgid "Remote"
-msgstr "внешний:"
+msgstr "Внешние репозитории"
 
 #: git-gui.sh:1807
 msgid "Browse Current Branch's Files"
 msgstr "Просмотреть файлы текущей ветви"
 
 #: git-gui.sh:1811
-#, fuzzy
 msgid "Browse Branch Files..."
-msgstr "Показать файлы ветви"
+msgstr "Показать файлы ветви..."
 
 #: git-gui.sh:1816
 msgid "Visualize Current Branch's History"
@@ -188,9 +183,9 @@ msgid "Visualize All Branch History"
 msgstr "История всех ветвей наглядно"
 
 #: git-gui.sh:1827
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Browse %s's Files"
-msgstr "Показать файлы ветви"
+msgstr "Показать файлы ветви %s"
 
 #: git-gui.sh:1829
 #, tcl-format
@@ -281,12 +276,10 @@ msgid "Rescan"
 msgstr "Перечитать"
 
 #: git-gui.sh:1953
-#, fuzzy
 msgid "Stage To Commit"
 msgstr "Подготовить для сохранения"
 
 #: git-gui.sh:1958
-#, fuzzy
 msgid "Stage Changed Files To Commit"
 msgstr "Подготовить измененные файлы для сохранения"
 
@@ -303,7 +296,6 @@ msgid "Sign Off"
 msgstr "Подписать"
 
 #: git-gui.sh:1980 git-gui.sh:2296
-#, fuzzy
 msgid "Commit@@verb"
 msgstr "Сохранить"
 
@@ -319,11 +311,10 @@ msgstr "Прервать объединение..."
 msgid "Push..."
 msgstr "Отправить..."
 
-# carbon copy
 #: git-gui.sh:2019 lib/choose_repository.tcl:41
 #, fuzzy
 msgid "Apple"
-msgstr "Apple"
+msgstr ""
 
 #: git-gui.sh:2022 git-gui.sh:2044 lib/about.tcl:13
 #: lib/choose_repository.tcl:44 lib/choose_repository.tcl:50
@@ -347,9 +338,8 @@ msgstr "Помощь"
 msgid "Online Documentation"
 msgstr "Документация в интернете"
 
-# TOVERIFY
 #: git-gui.sh:2165
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "fatal: cannot stat path %s: No such file or directory"
 msgstr "критическая ошибка: %s: нет такого файла или каталога"
 
@@ -358,43 +348,34 @@ msgid "Current Branch:"
 msgstr "Текущая ветвь:"
 
 #: git-gui.sh:2219
-#, fuzzy
 msgid "Staged Changes (Will Commit)"
 msgstr "Подготовлено (будет сохранено)"
 
-# TOVERIFY
 #: git-gui.sh:2239
-#, fuzzy
 msgid "Unstaged Changes"
-msgstr "Изменено"
+msgstr "Изменено (не будет сохранено)"
 
-# carbon copy
 #: git-gui.sh:2286
-#, fuzzy
 msgid "Stage Changed"
-msgstr "Stage Changed"
+msgstr "Подготовить все"
 
 #: git-gui.sh:2302 lib/transport.tcl:93 lib/transport.tcl:182
 msgid "Push"
 msgstr "Отправить"
 
 #: git-gui.sh:2332
-#, fuzzy
 msgid "Initial Commit Message:"
-msgstr "Первоначальный комментарий к состоянию:"
+msgstr "Комментарий к первому состоянию:"
 
 #: git-gui.sh:2333
-#, fuzzy
 msgid "Amended Commit Message:"
-msgstr "Исправленный комментарий к состоянию:"
+msgstr "Комментарий к исправленному состоянию:"
 
 #: git-gui.sh:2334
-#, fuzzy
 msgid "Amended Initial Commit Message:"
-msgstr "Первоначальный комментарий к исправленному состоянию:"
+msgstr "Комментарий к исправленному первоначальному состоянию:"
 
 #: git-gui.sh:2335
-#, fuzzy
 msgid "Amended Merge Commit Message:"
 msgstr "Комментарий к исправленному объединению:"
 
@@ -467,9 +448,7 @@ msgstr ""
 "запущенными из %s\n"
 "\n"
 
-# TOVERIFY
 #: git-gui.sh:2707
-#, fuzzy
 msgid ""
 "\n"
 "This is due to a known issue with the\n"
@@ -491,10 +470,10 @@ msgid ""
 msgstr ""
 "\n"
 "\n"
-"Хорошая замена для %s\n"
-"сохраняет значения для user.name и\n"
-"user.email в Ваш персональный\n"
-"~/.gitconfig файл.\n"
+"Вместо использования %s можно\n"
+"сохранить значения user.name и\n"
+"user.email в Вашем персональном\n"
+"файле ~/.gitconfig.\n"
 
 #: lib/about.tcl:25
 msgid "git-gui - a graphical user interface for Git."
@@ -510,69 +489,56 @@ msgstr "Сохраненное состояние:"
 
 #: lib/blame.tcl:249
 msgid "Copy Commit"
-msgstr "Копировать сохраненное состояние"
+msgstr "Скопировать SHA-1"
 
 #: lib/blame.tcl:369
 #, tcl-format
 msgid "Reading %s..."
 msgstr "Чтение %s..."
 
-# carbon copy
 #: lib/blame.tcl:473
-#, fuzzy
 msgid "Loading copy/move tracking annotations..."
-msgstr "Loading copy/move tracking annotations..."
+msgstr "Загрузка аннотации копирований/переименований..."
 
-# TOVERIFY
 #: lib/blame.tcl:493
-#, fuzzy
 msgid "lines annotated"
-msgstr "строк прокоментировано"
+msgstr "строк прокомментировано"
 
-# carbon copy
 #: lib/blame.tcl:674
-#, fuzzy
 msgid "Loading original location annotations..."
-msgstr "Loading original location annotations..."
+msgstr "Загрузка аннотаций первоначального положения объекта..."
 
-# carbon copy
 #: lib/blame.tcl:677
-#, fuzzy
 msgid "Annotation complete."
-msgstr "Annotation complete."
+msgstr "Аннотация завершена."
 
 #: lib/blame.tcl:731
-#, fuzzy
 msgid "Loading annotation..."
-msgstr "Загрузка %s..."
+msgstr "Загрузка аннотации..."
 
 #: lib/blame.tcl:787
 msgid "Author:"
 msgstr "Автор:"
 
 #: lib/blame.tcl:791
-#, fuzzy
 msgid "Committer:"
-msgstr "Сохраненное состояние:"
+msgstr "Сохранил:"
 
 #: lib/blame.tcl:796
 msgid "Original File:"
 msgstr "Исходный файл:"
 
-# carbon copy
 #: lib/blame.tcl:910
-#, fuzzy
 msgid "Originally By:"
-msgstr "Originally By:"
+msgstr "Источник:"
 
 #: lib/blame.tcl:916
-#, fuzzy
 msgid "In File:"
 msgstr "Файл:"
 
 #: lib/blame.tcl:921
 msgid "Copied Or Moved Here By:"
-msgstr "Кто скопировал/переместил сюда:"
+msgstr "Скопировано/перемещено в:"
 
 #: lib/branch_checkout.tcl:14 lib/branch_checkout.tcl:19
 msgid "Checkout Branch"
@@ -702,7 +668,7 @@ msgid ""
 "\n"
 " Delete the selected branches?"
 msgstr ""
-"Восстановить удаленную ветвь сложно. \n"
+"Восстанавливать удаленные ветви сложно. \n"
 "\n"
 " Удалить выбранные ветви?"
 
@@ -773,14 +739,14 @@ msgid "Browse"
 msgstr "Показать"
 
 #: lib/checkout_op.tcl:79
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Fetching %s from %s"
-msgstr "Получение изменений из %s "
+msgstr "Получение %s из %s "
 
 #: lib/checkout_op.tcl:127
 #, tcl-format
 msgid "fatal: Cannot resolve %s"
-msgstr "критическая ошибка: не могу распознать %s"
+msgstr "критическая ошибка: невозможно разрешить %s"
 
 #: lib/checkout_op.tcl:140 lib/console.tcl:79 lib/database.tcl:31
 msgid "Close"
@@ -807,7 +773,7 @@ msgstr ""
 #: lib/checkout_op.tcl:220
 #, tcl-format
 msgid "Merge strategy '%s' not supported."
-msgstr "Операция объединения '%s' не поддерживается."
+msgstr "Стратегия объединения '%s' не поддерживается."
 
 #: lib/checkout_op.tcl:239
 #, tcl-format
@@ -815,9 +781,8 @@ msgid "Failed to update '%s'."
 msgstr "Не удалось обновить '%s'."
 
 #: lib/checkout_op.tcl:251
-#, fuzzy
 msgid "Staging area (index) is already locked."
-msgstr "Индекс заблокирован."
+msgstr "Рабочая область заблокирована другим процессом."
 
 #: lib/checkout_op.tcl:266
 msgid ""
@@ -829,14 +794,15 @@ msgid ""
 msgstr ""
 "Последнее прочитанное состояние репозитория не соответствует текущему.\n"
 "\n"
-"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
+"С момента последней проверки репозиторий был изменен другой программой Git. "
+"Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n"
 "\n"
 "Это будет сделано сейчас автоматически.\n"
 
 #: lib/checkout_op.tcl:322
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Updating working directory to '%s'..."
-msgstr "Отсутствует рабочий каталог"
+msgstr "Обновление рабочего каталога из '%s'..."
 
 #: lib/checkout_op.tcl:353
 #, tcl-format
@@ -863,9 +829,9 @@ msgstr ""
 "Если вы хотите снова вернуться к какой-нибудь ветви, создайте ее сейчас, начиная с 'Текущего отсоединенного состояния'."
 
 #: lib/checkout_op.tcl:446
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Checked out '%s'."
-msgstr "Перейти..."
+msgstr "Ветвь '%s' сделана текущей."
 
 #: lib/checkout_op.tcl:478
 #, tcl-format
@@ -901,7 +867,6 @@ msgstr ""
 "Этого не должно было произойти. %s завершается."
 
 #: lib/choose_font.tcl:39
-#, fuzzy
 msgid "Select"
 msgstr "Выделить все"
 
@@ -910,15 +875,13 @@ msgid "Font Family"
 msgstr "Шрифт"
 
 #: lib/choose_font.tcl:73
-#, fuzzy
 msgid "Font Size"
-msgstr "Уменьшить размер шрифта"
+msgstr "Размер шрифта"
 
 #: lib/choose_font.tcl:90
 msgid "Font Example"
 msgstr "Пример текста"
 
-# TOVERIFY: what's the Russian version of the font sample (see Windows Fonts).
 #: lib/choose_font.tcl:101
 msgid ""
 "This is example text.\n"
@@ -929,39 +892,34 @@ msgstr ""
 
 #: lib/choose_repository.tcl:25
 msgid "Git Gui"
-msgstr "Git Gui"
+msgstr ""
 
 #: lib/choose_repository.tcl:69 lib/choose_repository.tcl:204
-#, fuzzy
 msgid "Create New Repository"
-msgstr "Из репозитория"
+msgstr "Создать новый репозиторий"
 
 #: lib/choose_repository.tcl:74 lib/choose_repository.tcl:291
-#, fuzzy
 msgid "Clone Existing Repository"
-msgstr "Репозиторий назначения"
+msgstr "Склонировать существующий репозиторий"
 
 #: lib/choose_repository.tcl:79 lib/choose_repository.tcl:800
-#, fuzzy
 msgid "Open Existing Repository"
-msgstr "Репозиторий назначения"
+msgstr "Выбрать существующий репозиторий"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:91
-#, fuzzy
 msgid "Next >"
 msgstr "Дальше >"
 
 #: lib/choose_repository.tcl:152
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Location %s already exists."
-msgstr "Ветвь '%s' уже существует."
+msgstr "Путь '%s' уже существует."
 
 #: lib/choose_repository.tcl:158 lib/choose_repository.tcl:165
 #: lib/choose_repository.tcl:172
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Failed to create repository %s:"
-msgstr "Не удалось полностью сохранить настройки:"
+msgstr "Не удалось создать репозиторий %s:"
 
 #: lib/choose_repository.tcl:209 lib/choose_repository.tcl:309
 msgid "Directory:"
@@ -969,121 +927,98 @@ msgstr "Каталог:"
 
 #: lib/choose_repository.tcl:238 lib/choose_repository.tcl:363
 #: lib/choose_repository.tcl:834
-#, fuzzy
 msgid "Git Repository"
 msgstr "Репозиторий"
 
 #: lib/choose_repository.tcl:253 lib/choose_repository.tcl:260
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Directory %s already exists."
-msgstr "Ветвь '%s' уже существует."
+msgstr "Каталог '%s' уже существует."
 
 #: lib/choose_repository.tcl:265
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "File %s already exists."
-msgstr "Ветвь '%s' уже существует."
+msgstr "Файл '%s' уже существует."
 
 #: lib/choose_repository.tcl:286
-#, fuzzy
 msgid "Clone"
-msgstr "Закрыть"
+msgstr "Склонировать"
 
 #: lib/choose_repository.tcl:299
 msgid "URL:"
 msgstr "Ссылка:"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:319
-#, fuzzy
 msgid "Clone Type:"
 msgstr "Тип клона:"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:325
-#, fuzzy
 msgid "Standard (Fast, Semi-Redundant, Hardlinks)"
 msgstr "Стандартный (Быстрый, полуизбыточный, \"жесткие\" ссылки)"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:331
-#, fuzzy
 msgid "Full Copy (Slower, Redundant Backup)"
-msgstr "Полная копия (Медленный, избыточная резервная копия)"
+msgstr "Полная копия (Медленный, создает резервную копию)"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:337
-#, fuzzy
 msgid "Shared (Fastest, Not Recommended, No Backup)"
 msgstr "Общий (Самый быстрый, не рекомендуется, без резервной копии)"
 
 #: lib/choose_repository.tcl:369 lib/choose_repository.tcl:418
 #: lib/choose_repository.tcl:560 lib/choose_repository.tcl:630
 #: lib/choose_repository.tcl:840 lib/choose_repository.tcl:848
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Not a Git repository: %s"
-msgstr "Не указан репозиторий"
+msgstr "Каталог не является репозиторием: %s"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:405
-#, fuzzy
 msgid "Standard only available for local repository."
 msgstr "Стандартный клон возможен только для локального репозитория."
 
-# TOVERIFY
 #: lib/choose_repository.tcl:409
-#, fuzzy
 msgid "Shared only available for local repository."
 msgstr "Общий клон возможен только для локального репозитория."
 
-# TOVERIFY
 #: lib/choose_repository.tcl:439
-#, fuzzy
 msgid "Failed to configure origin"
-msgstr "Не могу сконфигурировать искходник."
+msgstr "Не могу сконфигурировать исходный репозиторий."
 
 #: lib/choose_repository.tcl:451
 msgid "Counting objects"
 msgstr "Считаю объекты"
 
-# carbon copy
 #: lib/choose_repository.tcl:452
 #, fuzzy
 msgid "buckets"
-msgstr "buckets"
+msgstr ""
 
-# TOVERIFY
 #: lib/choose_repository.tcl:476
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Unable to copy objects/info/alternates: %s"
-msgstr "Не могу скопировать объекты/инфо/альтернативы: %s"
+msgstr "Не могу скопировать objects/info/alternates: %s"
 
 #: lib/choose_repository.tcl:512
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Nothing to clone from %s."
-msgstr "Получение изменений из %s "
+msgstr "Нечего клонировать с %s."
 
-# TOVERIFY
 #: lib/choose_repository.tcl:514 lib/choose_repository.tcl:728
 #: lib/choose_repository.tcl:740
-#, fuzzy
 msgid "The 'master' branch has not been initialized."
 msgstr "Не инициализирована ветвь 'master'."
 
-# TOVERIFY
 #: lib/choose_repository.tcl:527
-#, fuzzy
 msgid "Hardlinks are unavailable.  Falling back to copying."
 msgstr "\"Жесткие ссылки\" не доступны. Буду использовать копирование."
 
 #: lib/choose_repository.tcl:539
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Cloning from %s"
-msgstr "Получение изменений из %s "
+msgstr "Клонирование %s"
 
 #: lib/choose_repository.tcl:570
-#, fuzzy
 msgid "Copying objects"
-msgstr "Сжатие базы объектов"
+msgstr "Копирование objects"
 
 #: lib/choose_repository.tcl:571
 msgid "KiB"
@@ -1096,42 +1031,33 @@ msgstr "Не могу скопировать объект: %s"
 
 #: lib/choose_repository.tcl:605
 msgid "Linking objects"
-msgstr "Связываю объекты"
+msgstr "Создание ссылок на objects"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:606
-#, fuzzy
 msgid "objects"
-msgstr "объектов"
+msgstr "объекты"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:614
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Unable to hardlink object: %s"
 msgstr "Не могу \"жестко связать\" объект: %s"
 
-# TOVERIFY
 #: lib/choose_repository.tcl:669
-#, fuzzy
 msgid "Cannot fetch branches and objects.  See console output for details."
-msgstr "Не могу получить ветви и объекты. Детали - на консоле."
+msgstr "Не могу получить ветви и объекты. Дополнительная информация на консоли."
 
-# TOVERIFY
 #: lib/choose_repository.tcl:680
-#, fuzzy
 msgid "Cannot fetch tags.  See console output for details."
-msgstr "Не могу получить таги. Детали - на консоле."
+msgstr "Не могу получить метки. Дополнительная информация на консоли."
 
-# TOVERIFY
 #: lib/choose_repository.tcl:704
-#, fuzzy
 msgid "Cannot determine HEAD.  See console output for details."
-msgstr "Не могу определить главную ветвь. Детали - на консоле."
+msgstr "Не могу определить HEAD. Дополнительная информация на консоли."
 
 #: lib/choose_repository.tcl:713
 #, tcl-format
 msgid "Unable to cleanup %s"
-msgstr "Не могу почистить %s"
+msgstr "Не могу очистить %s"
 
 #: lib/choose_repository.tcl:719
 msgid "Clone failed."
@@ -1139,7 +1065,7 @@ msgstr "Клонирование не удалось."
 
 #: lib/choose_repository.tcl:726
 msgid "No default branch obtained."
-msgstr "Не возможно получить ветвь по умолчанию."
+msgstr "Не было получено ветви по умолчанию."
 
 #: lib/choose_repository.tcl:737
 #, tcl-format
@@ -1147,9 +1073,8 @@ msgid "Cannot resolve %s as a commit."
 msgstr "Не могу распознать %s как состояние."
 
 #: lib/choose_repository.tcl:749
-#, fuzzy
 msgid "Creating working directory"
-msgstr "Отсутствует рабочий каталог"
+msgstr "Создаю рабочий каталог"
 
 #: lib/choose_repository.tcl:750 lib/index.tcl:15 lib/index.tcl:80
 #: lib/index.tcl:149
@@ -1158,21 +1083,20 @@ msgstr "файлов"
 
 #: lib/choose_repository.tcl:779
 msgid "Initial file checkout failed."
-msgstr "Первое получение файла не удалось."
+msgstr "Не удалось получить начальное состояние файлов репозитория."
 
 #: lib/choose_repository.tcl:795
 msgid "Open"
 msgstr "Открыть"
 
 #: lib/choose_repository.tcl:805
-#, fuzzy
 msgid "Repository:"
-msgstr "Репозиторий"
+msgstr "Репозиторий:"
 
 #: lib/choose_repository.tcl:854
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Failed to open repository %s:"
-msgstr "Не удалось полностью сохранить настройки:"
+msgstr "Не удалось открыть репозиторий %s:"
 
 #: lib/choose_rev.tcl:53
 msgid "This Detached Checkout"
@@ -1205,7 +1129,7 @@ msgstr "Версия не указана."
 
 #: lib/choose_rev.tcl:346
 msgid "Revision expression is empty."
-msgstr "Пустое выражения для определения версии."
+msgstr "Пустое выражение для определения версии."
 
 #: lib/choose_rev.tcl:530
 msgid "Updated"
@@ -1223,7 +1147,7 @@ msgid ""
 msgstr ""
 "Отсутствует состояние для исправления.\n"
 "\n"
-"Вы можете создать начальное сохраненное состояние. Других состояний для исправления нет.\n"
+"Вы создаете первое состояние в репозитории, здесь еще нечего исправлять.\n"
 
 #: lib/commit.tcl:18
 msgid ""
@@ -1257,12 +1181,12 @@ msgid ""
 msgstr ""
 "Последнее прочитанное состояние репозитория не соответствует текущему.\n"
 "\n"
-"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
+"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
 "\n"
 "Это будет сделано сейчас автоматически.\n"
 
 #: lib/commit.tcl:154
-#, fuzzy, tcl-format
+#, tcl-format
 msgid ""
 "Unmerged files cannot be committed.\n"
 "\n"
@@ -1284,7 +1208,6 @@ msgstr ""
 "Файл %s не может быть сохранен данной программой.\n"
 
 #: lib/commit.tcl:170
-#, fuzzy
 msgid ""
 "No changes to commit.\n"
 "\n"
@@ -1416,14 +1339,14 @@ msgid ""
 msgstr ""
 "Этот репозиторий сейчас содержит примерно %i свободных объектов\n"
 "\n"
-"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i свободных объектов.\n"
+"Для лучшей производительности рекомендуется сжать базу данных, когда есть более %i несвязанных объектов.\n"
 "\n"
 "Сжать базу данных сейчас?"
 
 #: lib/date.tcl:25
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Invalid date from Git: %s"
-msgstr "Неверная версия: %s"
+msgstr "Неправильная дата в репозитории: %s"
 
 #: lib/diff.tcl:42
 #, tcl-format
@@ -1445,9 +1368,9 @@ msgstr ""
 "Сейчас будет запущено перечитывание репозитория, чтобы найти подобные файлы."
 
 #: lib/diff.tcl:81
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Loading diff of %s..."
-msgstr "Загрузка %s..."
+msgstr "Загрузка изменений в %s..."
 
 #: lib/diff.tcl:114 lib/diff.tcl:184
 #, tcl-format
@@ -1460,7 +1383,7 @@ msgstr "Ошибка загрузки файла:"
 
 #: lib/diff.tcl:122
 msgid "Git Repository (subproject)"
-msgstr "Репозиторий Git (под-проект)"
+msgstr "Репозиторий Git (подпроект)"
 
 #: lib/diff.tcl:134
 msgid "* Binary file (not showing content)."
@@ -1472,11 +1395,11 @@ msgstr "Ошибка загрузки diff:"
 
 #: lib/diff.tcl:302
 msgid "Failed to unstage selected hunk."
-msgstr "Не удалось исключить выбранную часть"
+msgstr "Не удалось исключить выбранную часть."
 
 #: lib/diff.tcl:309
 msgid "Failed to stage selected hunk."
-msgstr "Не удалось подготовить к сохранению выбранную часть"
+msgstr "Не удалось подготовить к сохранению выбранную часть."
 
 #: lib/error.tcl:12 lib/error.tcl:102
 msgid "error"
@@ -1491,19 +1414,19 @@ msgid "You must correct the above errors before committing."
 msgstr "Прежде чем сохранить, исправьте вышеуказанные ошибки."
 
 #: lib/index.tcl:241
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Unstaging %s from commit"
-msgstr "Убрать из подготовленного"
+msgstr "Удаление %s из подготовленного"
 
 #: lib/index.tcl:285
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Adding %s"
-msgstr "Чтение %s..."
+msgstr "Добавление %s..."
 
 #: lib/index.tcl:340
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "Revert changes in file %s?"
-msgstr "Отменить изменения"
+msgstr "Отменить изменения в файле %s?"
 
 #: lib/index.tcl:342
 #, tcl-format
@@ -1511,11 +1434,8 @@ msgid "Revert changes in these %i files?"
 msgstr "Отменить изменения в %i файле(-ах)?"
 
 #: lib/index.tcl:348
-#, fuzzy
 msgid "Any unstaged changes will be permanently lost by the revert."
 msgstr ""
-"Отменить изменения в %s?\n"
-"\n"
 "Любые изменения, не подготовленные к сохранению, будут потеряны при данной операции."
 
 #: lib/index.tcl:351
@@ -1542,12 +1462,12 @@ msgid ""
 msgstr ""
 "Последнее прочитанное состояние репозитория не соответствует текущему.\n"
 "\n"
-"С момента последней проверки репозиторий был изменен другой программой Git.Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь. \n"
+"С момента последней проверки репозиторий был изменен другой программой Git. Необходимо перечитать репозиторий, прежде чем изменять текущую ветвь.\n"
 "\n"
 "Это будет сделано сейчас автоматически.\n"
 
 #: lib/merge.tcl:44
-#, fuzzy, tcl-format
+#, tcl-format
 msgid ""
 "You are in the middle of a conflicted merge.\n"
 "\n"
@@ -1599,9 +1519,8 @@ msgid "Merge Into %s"
 msgstr "Объединить с %s"
 
 #: lib/merge.tcl:177
-#, fuzzy
 msgid "Revision To Merge"
-msgstr "Версия"
+msgstr "Версия для объединения"
 
 #: lib/merge.tcl:212
 msgid ""
@@ -1622,12 +1541,12 @@ msgid ""
 "Continue with aborting the current merge?"
 msgstr ""
 "Прервать объединение?\n"
+"\n"
 "Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n"
 "\n"
 "Продолжить?"
 
 #: lib/merge.tcl:228
-#, fuzzy
 msgid ""
 "Reset changes?\n"
 "\n"
@@ -1636,6 +1555,7 @@ msgid ""
 "Continue with resetting the current changes?"
 msgstr ""
 "Прервать объединение?\n"
+"\n"
 "Прерывание объединения приведет к потере *ВСЕХ* несохраненных изменений.\n"
 "\n"
 "Продолжить?"
@@ -1663,7 +1583,7 @@ msgstr "Сохранить"
 #: lib/option.tcl:96
 #, tcl-format
 msgid "%s Repository"
-msgstr "для репозитория %s "
+msgstr "для репозитория %s"
 
 #: lib/option.tcl:97
 msgid "Global (All Repositories)"
@@ -1710,7 +1630,6 @@ msgid "New Branch Name Template"
 msgstr "Шаблон для имени новой ветви"
 
 #: lib/option.tcl:176
-#, fuzzy
 msgid "Change Font"
 msgstr "Шрифт интерфейса"
 
@@ -1723,7 +1642,7 @@ msgstr "Выберите %s"
 #: lib/option.tcl:186
 #, fuzzy
 msgid "pt."
-msgstr "pt."
+msgstr ""
 
 #: lib/option.tcl:200
 msgid "Preferences"
@@ -1734,17 +1653,14 @@ msgid "Failed to completely save options:"
 msgstr "Не удалось полностью сохранить настройки:"
 
 #: lib/remote.tcl:165
-#, fuzzy
 msgid "Prune from"
-msgstr "Чистка %s... "
+msgstr "Чистка"
 
 #: lib/remote.tcl:170
-#, fuzzy
 msgid "Fetch from"
-msgstr "Чистка %s... "
+msgstr "Получение из"
 
 #: lib/remote.tcl:213
-#, fuzzy
 msgid "Push to"
 msgstr "Отправить"
 
@@ -1785,18 +1701,22 @@ msgid "A branch is required for 'Merged Into'."
 msgstr "Для опции 'Объединено с' требуется указать ветвь."
 
 #: lib/remote_branch_delete.tcl:184
-#, fuzzy, tcl-format
+#, tcl-format
 msgid ""
 "The following branches are not completely merged into %s:\n"
 "\n"
 " - %s"
-msgstr "Следующие ветви объединены с %s не полностью:"
+msgstr ""
+"Следующие ветви объединены с %s не полностью:"
+"\n"
+" - %s"
 
-# TOVERIFY
 #: lib/remote_branch_delete.tcl:189
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "One or more of the merge tests failed because you have not fetched the necessary commits.  Try fetching from %s first."
-msgstr "Один или несколько тестов на объединение не прошли, потому что Вы не получили необходимые состояния. Попробуйте сначала получить из %s."
+msgstr ""
+"Один или несколько тестов на объединение не прошли, потому что "
+"Вы не получили необходимые состояния. Попробуйте сначала получить их из %s."
 
 #: lib/remote_branch_delete.tcl:207
 msgid "Please select one or more branches to delete."
@@ -1819,7 +1739,7 @@ msgstr "Удаление ветвей из %s"
 
 #: lib/remote_branch_delete.tcl:286
 msgid "No repository selected."
-msgstr "Не указан репозиторий"
+msgstr "Не указан репозиторий."
 
 #: lib/remote_branch_delete.tcl:291
 #, tcl-format
@@ -1840,9 +1760,9 @@ msgid "%s ... %*i of %*i %s (%3i%%)"
 msgstr "%s ... %*i из %*i %s (%3i%%)"
 
 #: lib/transport.tcl:6
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "fetch %s"
-msgstr "Получить"
+msgstr "получение %s"
 
 #: lib/transport.tcl:7
 #, tcl-format
@@ -1851,9 +1771,9 @@ msgstr "Получение изменений из %s "
 
 # carbon copy
 #: lib/transport.tcl:18
-#, fuzzy, tcl-format
+#, tcl-format
 msgid "remote prune %s"
-msgstr "remote prune %s"
+msgstr "чистка внешнего %s"
 
 #: lib/transport.tcl:19
 #, tcl-format
@@ -1877,7 +1797,7 @@ msgstr "Отправка %s %s в %s"
 
 #: lib/transport.tcl:89
 msgid "Push Branches"
-msgstr "Отправить изменения"
+msgstr "Отправить изменения в ветвях"
 
 #: lib/transport.tcl:103
 msgid "Source Branches"
@@ -1889,7 +1809,7 @@ msgstr "Репозиторий назначения"
 
 #: lib/transport.tcl:158
 msgid "Transfer Options"
-msgstr "Настройки передачи"
+msgstr "Настройки отправки"
 
 #: lib/transport.tcl:160
 msgid "Force overwrite existing branch (may discard changes)"
@@ -1903,31 +1823,3 @@ msgstr "Использовать thin pack (для медленных сетев
 msgid "Include tags"
 msgstr "Включить метки"
 
-#~ msgid "Cannot find the git directory:"
-#~ msgstr "Каталог Git не найден:"
-#~ msgid "Add To Commit"
-#~ msgstr "Подготовить к сохранению"
-#~ msgid "Add Existing To Commit"
-#~ msgstr "Подготовить имеющиеся файлы к сохранению"
-#~ msgid "Unstaged Changes (Will Not Be Committed)"
-#~ msgstr "Изменено (не будет сохранено)"
-#~ msgid "Add Existing"
-#~ msgstr "Добавить имеющиеся файлы"
-#~ msgid ""
-#~ "Abort commit?\n"
-#~ "\n"
-#~ "Aborting the current commit will cause *ALL* uncommitted changes to be "
-#~ "lost.\n"
-#~ "\n"
-#~ "Continue with aborting the current commit?"
-#~ msgstr ""
-#~ "Отменить изменения?\n"
-#~ "\n"
-#~ "Вызванная операция приведет к потере *ВСЕХ* несохраненных изменений.\n"
-#~ "\n"
-#~ "Продолжить?"
-#~ msgid "Aborting... please wait..."
-#~ msgstr "Прерывание выполнения... Пожалуйста, ждите..."
-#~ msgid "Push to %s..."
-#~ msgstr "Отправка в %s..."
-
-- 
1.5.3.4.245.g150b

^ permalink raw reply related

* Re: [PATCH] Add color to git-add--interactive diffs (Total different idea to solve the problem)
From: Peter Baumann @ 2007-10-22 20:47 UTC (permalink / raw)
  To: Tom Tobin
  Cc: Dan Zwell, Jonathan del Strother, Johannes Schindelin,
	Shawn O. Pearce, Git Mailing List
In-Reply-To: <1192351494.7226.18.camel@athena>

On Sun, Oct 14, 2007 at 03:44:54AM -0500, Tom Tobin wrote:
> (This is repost; my damned mail client wrapped a line in the patch last
> time, and now I've got that under control.  My apologies!)  :(
> 
> Seeing the recent discussion and code regarding adding color to
> git-add--interactive, I thought I'd throw in my recent attempt at
> colorizing the diffs.  (This doesn't handle anything else, such as the
> prompts.)
> 
> After banging my head against parsing colorized output of git-add-files,
> I gave up and implemented internal colorization keying off of the
> color.diff configuration.
> 
> Hopefully this can be of some use towards fully colorizing
> git-add--interactive; I'll admit up front that Perl isn't my primary
> language, so I apologize in advance for whatever stupidities I've
> introduced.  ;) 
> 
> Signed-off-by: Tom Tobin <korpios@korpios.com>

[...skiping patch ...]

Tossing around ideas, so feel free to ignore me.

Wouldn't it make more sense to implement the diff coloring inside git apply
so that you could use something like

        diff file1 file2|git apply --color

to make the generated diff with colors [1]? It already implements the
same semantic for generating a diffstat, using

        diff file1 file2|git apply --stat

so we would get a generic diff colorizing tool and you could use inside
git add -i the diff without color and just print it out with the
git apply --color filter. So if someone implements another tool which
needs color handling he could use this output filter.

-Peter

[1]: there is a programm colordiff which does exactly this, but AFAIK git
     colorization has more features.

^ permalink raw reply

* Re: [PATCH] use only the PATH for exec'ing git commands
From: Alex Riesen @ 2007-10-22 20:57 UTC (permalink / raw)
  To: Scott R Parish; +Cc: git
In-Reply-To: <1193083141.v2.fusewebmail-240137@f>

Scott R Parish, Mon, Oct 22, 2007 21:59:01 +0200:
> > > +        if (old_path)
> > > +                strbuf_addstr(&amp;new_path, old_path);
> > > +        else
> > > +                strbuf_addstr(&amp;new_path, "/usr/local/bin:/usr/bin:/bin");
> >
> > the default PATH is platform-dependent. Git is multi-platform.
> > You should consider putting the path list somewhere in Makefile,
> > config.mak or configure.
> >
> 
> The original code was already doing both of these things (see git.c's
> prepend_to_path())

Well, would be nice if your code was better in this respect.

Anyway, I suspect the mingw people will trash the code anyway sometime
(or not, which is just as well - it is a rare case).

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox