* Re: Allowing push --dry-run through fetch url
From: Junio C Hamano @ 2009-11-06 9:44 UTC (permalink / raw)
To: Mike Hommey; +Cc: git
In-Reply-To: <20091106073707.GA14881@glandium.org>
Mike Hommey <mh@glandium.org> writes:
> The typical use of both at the same time is to put an authenticated
> value for pushurl (ssh://, for example) and an anonymous one (git://,
> for example) for url.
>
> What has been annoying me lately is that git push --dry-run asks me
> for the ssh key or password. I know I could be using an ssh-agent, but
> that's not the point.
I actually sense a possible XY problem here.
What are you trying to achieve with "git push --dry-run", especially when
you would instead be doing an equivalent of "git fetch" (or "ls-remote")
but not storing what you learned from that session with a change like what
you are imagining?
The answer to the above question is the real reason "X".
It could be that what you are interested in is if you are ahead of the
other side. In other words, you would want to know if some branches
result in non-fast-forward error, causing you to re-fetch and re-merge (or
rebase).
And "push --dry-run" that fails would give you that information, if it
worked for you without authenticating. And that could be your "Y".
But doesn't "branch -v" give the necessary information for that purpose
and even a bit more? Couldn't "git fetch && git branch -v" be a better
solution for your real problem "X"?
It is a better solution _if_ the real problem you are trying to solve is
what I suspected above because:
(1) If you will end up fetching to make you ahead of them again, doing
"push --dry-run" to learn fast-forwardness first would still require
you to fetch from there anyway. With "git fetch && git branch -v",
you have already fetched when you learned that you are not ahead;
(2) When you learn from "git fetch && git branch -v" that you were indeed
ahead, you can push. In such a case, because you were ahead, the
fetch wouldn't have slurped a lot of data from the other end anyway,
so there is no real overhead for doing so.
(3) In either case, "branch -v" output would give you not just "is it
fast-forward?" but also "if not, by how much they have diverged" (in
addition to the commit message for the tip).
But this may not be an XY problem. I am just curious.
^ permalink raw reply
* Re: [PATCH] RFC Allow case insensitive search flag with git-grep for fixed-strings
From: Brian Collins @ 2009-11-06 9:22 UTC (permalink / raw)
To: Jeff King; +Cc: git
In-Reply-To: <20091106084855.GA20964@coredump.intra.peff.net>
2009/11/6 Jeff King <peff@peff.net>:
> You're in the right place (though judging from the response, nobody
> seemed to find your patch all that interesting...).
Heh, yeah it is a bit of a boring edge case but a TextMate plugin I am writing
requires this functionality.
> Tests? They help prove to us that your feature works, and also prevent
> us from accidentally breaking your feature in the future.
Ah yes that is what I was forgetting. Please see the amended patch including
test.
Thanks for your help
---
builtin-grep.c | 8 +++++---
grep.c | 16 ++++++++++++----
grep.h | 2 ++
t/t7002-grep.sh | 9 +++++++++
4 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/builtin-grep.c b/builtin-grep.c
index 761799d..c73f05b 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -367,7 +367,7 @@ static int external_grep(struct grep_opt *opt,
const char **paths, int cached)
push_arg("-h");
if (opt->regflags & REG_EXTENDED)
push_arg("-E");
- if (opt->regflags & REG_ICASE)
+ if (opt->caseless)
push_arg("-i");
if (opt->binary == GREP_BINARY_NOMATCH)
push_arg("-I");
@@ -706,8 +706,8 @@ int cmd_grep(int argc, const char **argv, const
char *prefix)
OPT_GROUP(""),
OPT_BOOLEAN('v', "invert-match", &opt.invert,
"show non-matching lines"),
- OPT_BIT('i', "ignore-case", &opt.regflags,
- "case insensitive matching", REG_ICASE),
+ OPT_BOOLEAN('i', "ignore-case", &opt.caseless,
+ "case insensitive matching"),
OPT_BOOLEAN('w', "word-regexp", &opt.word_regexp,
"match patterns only at word boundaries"),
OPT_SET_INT('a', "text", &opt.binary,
@@ -830,6 +830,8 @@ int cmd_grep(int argc, const char **argv, const
char *prefix)
external_grep_allowed = 0;
if (!opt.pattern_list)
die("no pattern given.");
+ if (!opt.fixed && opt.caseless)
+ opt.regflags |= REG_ICASE;
if ((opt.regflags != REG_NEWLINE) && opt.fixed)
die("cannot mix --fixed-strings and regexp");
compile_grep_patterns(&opt);
diff --git a/grep.c b/grep.c
index 5d162da..d8f14be 100644
--- a/grep.c
+++ b/grep.c
@@ -41,7 +41,8 @@ static void compile_regexp(struct grep_pat *p,
struct grep_opt *opt)
int err;
p->word_regexp = opt->word_regexp;
-
+ p->caseless = opt->caseless;
+
if (opt->fixed || is_fixed(p->pattern))
p->fixed = 1;
if (opt->regflags & REG_ICASE)
@@ -262,9 +263,16 @@ static void show_name(struct grep_opt *opt, const
char *name)
printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
}
-static int fixmatch(const char *pattern, char *line, regmatch_t *match)
+
+static int fixmatch(const char *pattern, char *line, int caseless,
regmatch_t *match)
{
- char *hit = strstr(line, pattern);
+ char *hit;
+ if (caseless) {
+ hit = strcasestr(line, pattern);
+ } else {
+ hit = strstr(line, pattern);
+ }
+
if (!hit) {
match->rm_so = match->rm_eo = -1;
return REG_NOMATCH;
@@ -326,7 +334,7 @@ static int match_one_pattern(struct grep_pat *p,
char *bol, char *eol,
again:
if (p->fixed)
- hit = !fixmatch(p->pattern, bol, pmatch);
+ hit = !fixmatch(p->pattern, bol, p->caseless, pmatch);
else
hit = !regexec(&p->regexp, bol, 1, pmatch, eflags);
diff --git a/grep.h b/grep.h
index f6eecc6..24b7d44 100644
--- a/grep.h
+++ b/grep.h
@@ -32,6 +32,7 @@ struct grep_pat {
enum grep_header_field field;
regex_t regexp;
unsigned fixed:1;
+ unsigned caseless:1;
unsigned word_regexp:1;
};
@@ -64,6 +65,7 @@ struct grep_opt {
regex_t regexp;
int linenum;
int invert;
+ int caseless;
int status_only;
int name_only;
int unmatch_name_only;
diff --git a/t/t7002-grep.sh b/t/t7002-grep.sh
index ae56a36..87b47dd 100755
--- a/t/t7002-grep.sh
+++ b/t/t7002-grep.sh
@@ -345,4 +345,13 @@ test_expect_success 'grep from a subdirectory to
search wider area (2)' '
)
'
+cat >expected <<EOF
+hello.c: return 0;
+EOF
+
+test_expect_success 'grep -Fi' '
+ git grep -Fi rEtUrN >actual &&
+ test_cmp expected actual
+'
+
test_done
--
1.6.4.4
^ permalink raw reply related
* Re: Allowing push --dry-run through fetch url
From: Mike Hommey @ 2009-11-06 9:21 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v4op82fh0.fsf@alter.siamese.dyndns.org>
On Fri, Nov 06, 2009 at 01:02:35AM -0800, Junio C Hamano wrote:
> > Maybe I'm missing something, but the only missing thing I can see at
> > first thought is whether the server is going to reject non fast-forward
> > updates. Are there any others ?
>
> Hooks, for a starter.
AFAICS, they are not run when using --dry-run.
Mike
^ permalink raw reply
* Re: Allowing push --dry-run through fetch url
From: Junio C Hamano @ 2009-11-06 9:02 UTC (permalink / raw)
To: Mike Hommey; +Cc: git
In-Reply-To: <20091106085917.GA497@glandium.org>
Mike Hommey <mh@glandium.org> writes:
> On Fri, Nov 06, 2009 at 12:49:49AM -0800, Junio C Hamano wrote:
>> The daemon sitting on the other end to serve "git://" URL won't understand
>> an attempt to push into. What goes over the wire in the fetch protocol
>> does not give your updated "git push" enough information to guess what
>> would happen if you pushed.
>
> Maybe I'm missing something, but the only missing thing I can see at
> first thought is whether the server is going to reject non fast-forward
> updates. Are there any others ?
Hooks, for a starter.
^ permalink raw reply
* Re: Allowing push --dry-run through fetch url
From: Mike Hommey @ 2009-11-06 8:59 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vtyx82g2a.fsf@alter.siamese.dyndns.org>
On Fri, Nov 06, 2009 at 12:49:49AM -0800, Junio C Hamano wrote:
> The daemon sitting on the other end to serve "git://" URL won't understand
> an attempt to push into. What goes over the wire in the fetch protocol
> does not give your updated "git push" enough information to guess what
> would happen if you pushed.
Maybe I'm missing something, but the only missing thing I can see at
first thought is whether the server is going to reject non fast-forward
updates. Are there any others ?
Mike
^ permalink raw reply
* Re: Allowing push --dry-run through fetch url
From: Junio C Hamano @ 2009-11-06 8:49 UTC (permalink / raw)
To: Mike Hommey; +Cc: git
In-Reply-To: <20091106073707.GA14881@glandium.org>
Mike Hommey <mh@glandium.org> writes:
> So, before I dive in, what would you think about such a feature?
The daemon sitting on the other end to serve "git://" URL won't understand
an attempt to push into. What goes over the wire in the fetch protocol
does not give your updated "git push" enough information to guess what
would happen if you pushed.
Of course, it is open source and everything can be modified. You _could_
change the daemon whose primary purpose has been to serve fetch requests
to also support dry-run only push to make what you outlined work.
But isn't it adding unnecessary complexity for no real reason? It would
be a tough sell, I would imagine.
^ permalink raw reply
* Re: [PATCH] RFC Allow case insensitive search flag with git-grep for fixed-strings
From: Jeff King @ 2009-11-06 8:48 UTC (permalink / raw)
To: Brian Collins; +Cc: git
In-Reply-To: <B7C4E16C-B15D-4A7B-873A-B6BD0FDAD8C8@gmail.com>
On Thu, Oct 29, 2009 at 06:21:59PM -0700, Brian Collins wrote:
> You will have to excuse me, this is my first patch and I don't know
> if this is the right place to post this. Apologies in advance if I'm
> in the wrong place.
You're in the right place (though judging from the response, nobody
seemed to find your patch all that interesting...).
> git-grep currently throws an error when you combine the -F and -i
> flags. This isn't in line with how GNU grep handles it. This patch
> allows the simultaneous use of those flags.
I don't see a reason not to allow this combination if our grep
implementation supports it. My only reservation would be that we
sometimes call out to an external grep, and non-GNU grep might barf on
this. But I think that is OK, as the user should get a sane error from
the external grep.
> builtin-grep.c | 8 +++++---
> grep.c | 16 ++++++++++++----
> grep.h | 2 ++
Tests? They help prove to us that your feature works, and also prevent
us from accidentally breaking your feature in the future.
-Peff
^ permalink raw reply
* Re: [PATCH] gitk: disable checkout of remote branch
From: Sverre Rabbelier @ 2009-11-06 8:30 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Jeff King, Tim Mazid, git
In-Reply-To: <7v8wek7a6z.fsf@alter.siamese.dyndns.org>
Heya,
On Fri, Nov 6, 2009 at 01:45, Junio C Hamano <gitster@pobox.com> wrote:
> Jeff King <peff@peff.net> writes:
>> Sorry, yes, I just saw Sverre's comment and misread the original
>> proposal. Checking out "$remote/$branch" will still detach the HEAD,
>> and I don't think anybody has a previous proposal to change that.
>
> Heh, I think both of us forgot that we decided it is safe enough not to
> wait for 1.7.0 already, because the situation this kicks in has always
> resulted in an error. We have it in master since e3de372 (Merge branch
> 'jc/checkout-auto-track', 2009-10-30).
Sorry for causing so much confusion, I misremembered what the patch
was about ("git checkout <branch>" vs "git checkout
<remote>/<branch>"). Apologies.
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: [PATCH] MSVC: Windows-native implementation for subset of Pthreads API
From: Johannes Sixt @ 2009-11-06 8:25 UTC (permalink / raw)
To: Andrzej K. Haczewski
Cc: git, Nicolas Pitre, kusmabite, Johannes Schindelin, Paolo Bonzini
In-Reply-To: <1257495059-12394-1-git-send-email-ahaczewski@gmail.com>
Andrzej K. Haczewski schrieb:
> One more round of that patch with Nicolas' comments considered, and
> disclamer about the implementation added.
>
> Johannes, can you replace previous commit with that patch?
Thanks; the result is in
git://repo.or.cz/git/mingw/j6t.git pthreads-for-windows
-- Hannes
^ permalink raw reply
* Re: [QGIT PATCH/RFC]
From: Abdelrazak Younes @ 2009-11-06 8:16 UTC (permalink / raw)
To: Marco Costalba; +Cc: git
In-Reply-To: <e5bfff550911051225s13c6e39dh355dc3ab1c0623f@mail.gmail.com>
Marco Costalba wrote:
> On Thu, Nov 5, 2009 at 11:37, Abdelrazak Younes <younes@lyx.org> wrote:
>
>> I recompiled qgit with the Qt version and I didn't notice any performance
>> problem with a big repo (Qt).
>>
>>
>
> In git we don't need to compute hashes of sha strings because they are
> already hashed !
>
Now you tell it, it's obvious indeed :-)
Thanks,
Abdel.
^ permalink raw reply
* Re: [QGIT PATCH/RFC]
From: Abdelrazak Younes @ 2009-11-06 8:15 UTC (permalink / raw)
To: Marco Costalba; +Cc: git
In-Reply-To: <e5bfff550911051227g257312b2idf729b9451d1bb@mail.gmail.com>
Marco Costalba wrote:
> On Thu, Nov 5, 2009 at 21:25, Marco Costalba <mcostalba@gmail.com> wrote:
>
>> When I tested I _found_ a speed difference, but now I don't remember
>> of how much. Be sure you have warm cache when doing the test (press
>> F5) for few times to be sure all is in RAM.
>>
>>
>
> Sorry, I forgot. Be sure also our custom hashing function is actually
> called in your binary and the compiler didn't linked the Qt one
> instead :-)
>
Yes I made sure of that (see my other mail).
Abdel.
^ permalink raw reply
* [PATCH] MSVC: Windows-native implementation for subset of Pthreads API
From: Andrzej K. Haczewski @ 2009-11-06 8:10 UTC (permalink / raw)
To: git
Cc: Andrzej K. Haczewski, Nicolas Pitre, kusmabite,
Johannes Schindelin, Johannes Sixt, Paolo Bonzini
In-Reply-To: <1257283802-29726-1-git-send-email-ahaczewski@gmail.com>
This patch implements native to Windows subset of pthreads API used by Git.
It allows to remove Pthreads for Win32 dependency for MSVC, msysgit and
Cygwin.
The patch modifies Makefile only for MSVC (that's the environment I'm
capable of testing on), so it requires further corrections to compile
with MinGW or Cygwin.
Signed-off-by: Andrzej K. Haczewski <ahaczewski@gmail.com>
---
One more round of that patch with Nicolas' comments considered, and
disclamer about the implementation added.
Johannes, can you replace previous commit with that patch?
Makefile | 7 ++-
builtin-pack-objects.c | 31 +++++++++++--
compat/mingw.c | 2 +-
compat/mingw.h | 5 ++
compat/win32/pthread.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++
compat/win32/pthread.h | 68 +++++++++++++++++++++++++++
6 files changed, 225 insertions(+), 8 deletions(-)
create mode 100644 compat/win32/pthread.c
create mode 100644 compat/win32/pthread.h
diff --git a/Makefile b/Makefile
index bc039ac..30089a8 100644
--- a/Makefile
+++ b/Makefile
@@ -453,6 +453,7 @@ LIB_H += commit.h
LIB_H += compat/bswap.h
LIB_H += compat/cygwin.h
LIB_H += compat/mingw.h
+LIB_H += compat/win32/pthread.h
LIB_H += csum-file.h
LIB_H += decorate.h
LIB_H += delta.h
@@ -971,15 +972,15 @@ ifdef MSVC
OBJECT_CREATION_USES_RENAMES = UnfortunatelyNeedsTo
NO_REGEX = YesPlease
NO_CURL = YesPlease
- NO_PTHREADS = YesPlease
+ THREADED_DELTA_SEARCH = YesPlease
BLK_SHA1 = YesPlease
CC = compat/vcbuild/scripts/clink.pl
AR = compat/vcbuild/scripts/lib.pl
CFLAGS =
BASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE
- COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o
- COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -DSTRIP_EXTENSION=\".exe\"
+ COMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o
+ COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib
lib =
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 02f9246..00594fd 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -1255,15 +1255,15 @@ static int delta_cacheable(unsigned long src_size, unsigned long trg_size,
#ifdef THREADED_DELTA_SEARCH
-static pthread_mutex_t read_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t read_mutex;
#define read_lock() pthread_mutex_lock(&read_mutex)
#define read_unlock() pthread_mutex_unlock(&read_mutex)
-static pthread_mutex_t cache_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t cache_mutex;
#define cache_lock() pthread_mutex_lock(&cache_mutex)
#define cache_unlock() pthread_mutex_unlock(&cache_mutex)
-static pthread_mutex_t progress_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t progress_mutex;
#define progress_lock() pthread_mutex_lock(&progress_mutex)
#define progress_unlock() pthread_mutex_unlock(&progress_mutex)
@@ -1590,7 +1590,26 @@ struct thread_params {
unsigned *processed;
};
-static pthread_cond_t progress_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t progress_cond;
+
+/*
+ * Mutex and conditional variable can't be statically-initialized on Windows.
+ */
+static void init_threaded_search()
+{
+ pthread_mutex_init(&read_mutex, NULL);
+ pthread_mutex_init(&cache_mutex, NULL);
+ pthread_mutex_init(&progress_mutex, NULL);
+ pthread_cond_init(&progress_cond, NULL);
+}
+
+static void cleanup_threaded_search()
+{
+ pthread_cond_destroy(&progress_cond);
+ pthread_mutex_destroy(&read_mutex);
+ pthread_mutex_destroy(&cache_mutex);
+ pthread_mutex_destroy(&progress_mutex);
+}
static void *threaded_find_deltas(void *arg)
{
@@ -1629,8 +1648,11 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
struct thread_params *p;
int i, ret, active_threads = 0;
+ init_threaded_search();
+
if (delta_search_threads <= 1) {
find_deltas(list, &list_size, window, depth, processed);
+ cleanup_threaded_search();
return;
}
if (progress > pack_to_stdout)
@@ -1745,6 +1767,7 @@ static void ll_find_deltas(struct object_entry **list, unsigned list_size,
active_threads--;
}
}
+ cleanup_threaded_search();
free(p);
}
diff --git a/compat/mingw.c b/compat/mingw.c
index 6b5b5b2..f2e9f02 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -5,7 +5,7 @@
#include <shellapi.h>
-static int err_win_to_posix(DWORD winerr)
+int err_win_to_posix(DWORD winerr)
{
int error = ENOSYS;
switch(winerr) {
diff --git a/compat/mingw.h b/compat/mingw.h
index 6907345..7e25fb5 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -294,3 +294,8 @@ struct mingw_dirent
#define readdir(x) mingw_readdir(x)
struct dirent *mingw_readdir(DIR *dir);
#endif // !NO_MINGW_REPLACE_READDIR
+
+/*
+ * Used by Pthread API implementation for Windows
+ */
+extern int err_win_to_posix(DWORD winerr);
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
new file mode 100644
index 0000000..652d7b4
--- /dev/null
+++ b/compat/win32/pthread.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com>
+ *
+ * DISCLAMER: The implementation is Git-specific, it is subset of original
+ * Pthreads API, without lots of other features that Git doesn't use.
+ * Git also makes sure that the passed arguments are valid, so there's
+ * no need for double-checking.
+ */
+
+#include "../../git-compat-util.h"
+#include "pthread.h"
+
+#include <errno.h>
+#include <limits.h>
+
+static unsigned __stdcall win32_start_routine(void *arg)
+{
+ pthread_t *thread = arg;
+ thread->arg = thread->start_routine(thread->arg);
+ return 0;
+}
+
+int pthread_create(pthread_t *thread, const void *unused,
+ void *(*start_routine)(void*), void *arg)
+{
+ thread->arg = arg;
+ thread->start_routine = start_routine;
+ thread->handle = (HANDLE)
+ _beginthreadex(NULL, 0, win32_start_routine, thread, 0, NULL);
+
+ if (!thread->handle)
+ return errno;
+ else
+ return 0;
+}
+
+int win32_pthread_join(pthread_t *thread, void **value_ptr)
+{
+ DWORD result = WaitForSingleObject(thread->handle, INFINITE);
+ switch (result) {
+ case WAIT_OBJECT_0:
+ if (value_ptr)
+ *value_ptr = thread->arg;
+ return 0;
+ case WAIT_ABANDONED:
+ return EINVAL;
+ default:
+ return err_win_to_posix(GetLastError());
+ }
+}
+
+int pthread_cond_init(pthread_cond_t *cond, const void *unused)
+{
+ cond->waiters = 0;
+
+ InitializeCriticalSection(&cond->waiters_lock);
+
+ cond->sema = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
+ if (!cond->sema)
+ die("CreateSemaphore() failed");
+ return 0;
+}
+
+int pthread_cond_destroy(pthread_cond_t *cond)
+{
+ CloseHandle(cond->sema);
+ cond->sema = NULL;
+
+ DeleteCriticalSection(&cond->waiters_lock);
+
+ return 0;
+}
+
+int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex)
+{
+ /* serialize access to waiters count */
+ EnterCriticalSection(&cond->waiters_lock);
+ ++cond->waiters;
+ LeaveCriticalSection(&cond->waiters_lock);
+
+ /*
+ * Unlock external mutex and wait for signal.
+ * NOTE: we've held mutex locked long enough to increment
+ * waiters count above, so there's no problem with
+ * leaving mutex unlocked before we wait on semaphore.
+ */
+ LeaveCriticalSection(mutex);
+
+ /* let's wait - ignore return value */
+ WaitForSingleObject(cond->sema, INFINITE);
+
+ /* we're done waiting, so make sure we decrease waiters count */
+ EnterCriticalSection(&cond->waiters_lock);
+ --cond->waiters;
+ LeaveCriticalSection(&cond->waiters_lock);
+
+ /* lock external mutex again */
+ EnterCriticalSection(mutex);
+
+ return 0;
+}
+
+int pthread_cond_signal(pthread_cond_t *cond)
+{
+ int have_waiters;
+
+ /* serialize access to waiters count */
+ EnterCriticalSection(&cond->waiters_lock);
+ have_waiters = cond->waiters > 0;
+ LeaveCriticalSection(&cond->waiters_lock);
+
+ /*
+ * Signal only when there are waiters
+ */
+ if (have_waiters)
+ return ReleaseSemaphore(cond->sema, 1, NULL) ?
+ 0 : err_win_to_posix(GetLastError());
+ else
+ return 0;
+}
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
new file mode 100644
index 0000000..63293ad
--- /dev/null
+++ b/compat/win32/pthread.h
@@ -0,0 +1,68 @@
+/*
+ * Header used to adapt pthread-based POSIX code to Windows API threads.
+ *
+ * Copyright (C) 2009 Andrzej K. Haczewski <ahaczewski@gmail.com>
+ */
+
+#ifndef PTHREAD_H
+#define PTHREAD_H
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include <windows.h>
+
+/*
+ * Defines that adapt Windows API threads to pthreads API
+ */
+#define pthread_mutex_t CRITICAL_SECTION
+
+#define pthread_mutex_init(a,b) InitializeCriticalSection((a))
+#define pthread_mutex_destroy(a) DeleteCriticalSection((a))
+#define pthread_mutex_lock EnterCriticalSection
+#define pthread_mutex_unlock LeaveCriticalSection
+
+/*
+ * Implement simple condition variable for Windows threads, based on ACE
+ * implementation.
+ *
+ * See original implementation: http://bit.ly/1vkDjo
+ * ACE homepage: http://www.cse.wustl.edu/~schmidt/ACE.html
+ * See also: http://www.cse.wustl.edu/~schmidt/win32-cv-1.html
+ */
+typedef struct {
+ LONG waiters;
+ CRITICAL_SECTION waiters_lock;
+ HANDLE sema;
+} pthread_cond_t;
+
+extern int pthread_cond_init(pthread_cond_t *cond, const void *unused);
+
+extern int pthread_cond_destroy(pthread_cond_t *cond);
+
+extern int pthread_cond_wait(pthread_cond_t *cond, CRITICAL_SECTION *mutex);
+
+extern int pthread_cond_signal(pthread_cond_t *cond);
+
+/*
+ * Simple thread creation implementation using pthread API
+ */
+typedef struct {
+ HANDLE handle;
+ void *(*start_routine)(void*);
+ void *arg;
+} pthread_t;
+
+extern int pthread_create(pthread_t *thread, const void *unused,
+ void *(*start_routine)(void*), void *arg);
+
+/*
+ * To avoid the need of copying a struct, we use small macro wrapper to pass
+ * pointer to win32_pthread_join instead.
+ */
+#define pthread_join(a, b) win32_pthread_join(&(a), (b))
+
+extern int win32_pthread_join(pthread_t *thread, void **value_ptr);
+
+#endif /* PTHREAD_H */
--
1.6.5.2
^ permalink raw reply related
* Allowing push --dry-run through fetch url
From: Mike Hommey @ 2009-11-06 7:37 UTC (permalink / raw)
To: git
Hi,
I am currently considering, when I'll get some time, to dive in the git
push code to allow push --dry-run without the rights to push.
We currently have two remote configuration items for urls:
remote.<name>.url and remote.<name>.pushurl. The latter is used when
pushing and the former when pulling/fetching.
The typical use of both at the same time is to put an authenticated
value for pushurl (ssh://, for example) and an anonymous one (git://,
for example) for url.
What has been annoying me lately is that git push --dry-run asks me
for the ssh key or password. I know I could be using an ssh-agent, but
that's not the point.
It would be interesting, to me at least, that git push --dry-run can do
its job through the git:// url instead of the ssh:// one. But for now,
all that does is telling me:
fatal: The remote end hung up unexpectedly
(probably because the git server doesn't allow pushes at all)
So, before I dive in, what would you think about such a feature?
There is one thing that bothers me, though, it's that --dry-run would,
in the end, not really be a dry-run anymore, and, for example, could
not be used to validate that the ssh setup is good without actually
pushing.
Cheers,
Mike
^ permalink raw reply
* Re: suggestions for local configs?
From: Johannes Sixt @ 2009-11-06 7:21 UTC (permalink / raw)
To: Tim Rupp; +Cc: git
In-Reply-To: <4AF393EE.4030205@gmail.com>
Tim Rupp schrieb:
> I have a piece of software that has default and local configuration
> files. The default files ship with the tarball. The local files are
> copied over from the default folder during installation and can be
> modified for a particular install.
This is how *I* would organize it, but it is a bit overengineered if the
changes needed in the configuration are only minimal:
---o--o--X1--o--o--X2--o master (aka upstream)
\ \ \
R-----M1------------M3 rename
\ \ \
Y-----M2------------M4 production
We need two branches in addition to master, which tracks upstream version.
1. The first branch *renames* the example configuration to the effective
configuration:
git mv foo.conf.example foo.conf
# commit R
git commit -m "Use the example configuration"
It is important that *no change* is made to the configuration file, and it
furthermore assumes that the production configuration (foo.conf) does not
exist [*].
The point of this commit is that git can determine that the file was
renamed with 100% similarity.
2. The second branch is actually where the customization happens, this is
commit Y:
git checkout production
edit foo.conf
# commit Y
git commit -m "configuration changes needed in production"
Assume, upstream made changes to the configuration (commit X1). These
changes are merged in the following way:
1. git checkout rename && git merge master
This creates M1. git detects that on our side the file was renamed, and
merges the upstream changes into the renamed file. Since we didn't modify
the file in R, there are no conflicts.
2. git checkout production && git merge rename
This creates M2. This is a regular merge that integrates upstream changes
with the local changes made in Y, possibly with conflicts.
You repeat the procedure when upstream makes more changes to the example
configuration in X2. This time, git merge again detects that the file was
renamed with 100% similarity, and things work just like with M1 and M2.
[*] If there is a configuration file in addition to the example
configuration, another branch is needed that removes it.
-- Hannes
^ permalink raw reply
* Re: [PATCH] pack-objects: move thread autodetection closer to relevant code
From: Junio C Hamano @ 2009-11-06 7:20 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Junio C Hamano, Andrzej K. Haczewski, git, Johannes Sixt
In-Reply-To: <alpine.LFD.2.00.0911041623570.10340@xanadu.home>
Nicolas Pitre <nico@fluxnic.net> writes:
> Let's keep thread stuff close together if possible. And in this case,
> this even reduces the #ifdef noise, and allows for skipping the
> autodetection altogether if delta search is not needed (like with a pure
> clone).
Nice. The ll_find_delta() function itself will disappear and becomes the
single-threaded find_deltas() when THREADED_DELTA_SEARCH is not defined,
and the variable in question is used only inside the function anyway, so
this works beautifully.
Very nice.
^ permalink raw reply
* Re: [PATCH/RFC 0/3] teach fetch --prune
From: Junio C Hamano @ 2009-11-06 7:05 UTC (permalink / raw)
To: Jay Soffian; +Cc: git
In-Reply-To: <1257484241-27219-1-git-send-email-jaysoffian@gmail.com>
Jay Soffian <jaysoffian@gmail.com> writes:
> This is just a start so I can get some feedback. Some things still missing:
>
> 1) "git remote prune <remote>" calls warn_dangling_symref(), but
> "git fetch --prune" does not. I ran out of time tonight to refactor
> warn_dangling_symref() to do something more intelligent than just spew to
> stdout (which doesn't get along with fetch, which spews to stderr...).
>
> 2) Perhaps "git remote update --prune" should be refactored to call
> "git fetch --prune". If so, then fetch should gain a "--prune-only" option
> so that "git remote prune" can just call "got fetch --prune-only".
>
> 3) Perhaps add a config option for users who wish to prune by default.
>
> Thoughts, comments, flames?
I usually refrain from talking about multi-year long term plans, because I
do not have one, but in a longer term (across 1.7.0 boundary and beyond),
the general direction would be:
- "fetch" will eventually prune by default; I expect we will have a
configuration option "fetch.autoprune = yes" to allow early adopters to
let it prune until 1.7.0, and in 1.7.0 we will change the default for
the configuration variable to "yes", i.e. we prune unless the user
explicitly declines with "fetch.autoprune = no".
- In general, "remote" should go back to its roots of being the
management interface to [remote "nick"] configuration section. We
should start planning to remove extra features that were piled on top
of the original "remote definition management tool". "update/prune"
should have been the duty of "fetch" in the first place, but they were
added to "remote" primarily because it was easier to do so ("remote"
used to be script but "fetch" was already written in "C").
This means two things:
* "remote prune" that only prunes without updating remaining tracking
will be largely become unnecessary [*1*], once we have a way to tell
"fetch" to prune at the same time. As soon as "fetch --prune"
becomes available, "remote prune" should become an alias to it. And
"remote prune" itself should eventually be removed.
* "remote update" that runs "fetch" for multiple remotes should be
deprecated and eventually removed. "remote update" is a band-aid
that exists only because "fetch" started as a strange chimera between
plumbing and Porcelain, and we did not want to add too much features
to it. "fetch" itself should learn to do the "from multiple places"
part as a full-fledged Porcelain.
Of course, a removal of a subcommand ("remote update" and "remote prune")
will have to happen way after 1.7.0 boundary, but the above should be the
longer term direction.
Don't worry about keeping the "only prune without updating" misfeature. If
omission of it simplifies what you are trying to do, it is Ok if "git
prune" becomes a synonym to "git update --prune" aka "git fetch --prune"
and starts updating the tracking refs.
[Footnote]
*1* "remote prune" is a band-aid that exists only because "fetch"
currently has no-way to prune at the same time.
One could argue that a user may want to prune _only_ stale refs without
getting the state of remaining refs updated to his tracking refs. That
certainly is _possible_ with "remote prune", but being possible and being
sensible are two different things.
What is the reason the user does not want to update a tracking ref that
corresponds to a branch that remains at the remote, when he runs "prune
only" version if it existed? It cannot be because the branch may have
been rewound and you may lose the only remaining history---the user is
actively asking to prune and is willing to lose the history of stale
branches.
In other words, once we have "fetch --prune" (either default or
optional---the important part is that there is a way to cause fetch to do
this), there is no sane reason to have a separate command that only prunes
without updating the remaining tracking refs.
^ permalink raw reply
* Re: [PATCH v2 09/13] Honour the refspec when updating refs after import
From: Junio C Hamano @ 2009-11-06 6:05 UTC (permalink / raw)
To: Daniel Barkalow
Cc: Sverre Rabbelier, Git List, Johannes Schindelin, Johan Herland,
Junio C Hamano
In-Reply-To: <alpine.LNX.2.00.0911051929340.14365@iabervon.org>
Daniel Barkalow <barkalow@iabervon.org> writes:
> On Fri, 6 Nov 2009, Sverre Rabbelier wrote:
>
>> > I don't know why Junio squashed your
>> > changes into my patch, particularly when I disagreed with those changes.
>>
>> Junio didn't squash anything, it's just that pu still contains v4 of
>> the series, in which I had squashed my changes in.
>
> Oh, okay. You probably shouldn't squash un-acked changes into other
> people's patches when taking over their series.
Thanks for having this exchange. You are right, and I should have more
explicitly explained what I was doing when I replaced two series (yours
and Johan's cvs series) with Sverre's consolidated re-roll.
^ permalink raw reply
* [PATCH/RFC 3/3] builtin-fetch: add --prune option
From: Jay Soffian @ 2009-11-06 5:10 UTC (permalink / raw)
To: git; +Cc: Jay Soffian
In-Reply-To: <1257484241-27219-3-git-send-email-jaysoffian@gmail.com>
Teach fetch --prune, as an alternative to git remote prune.
---
builtin-fetch.c | 22 +++++++++++++++++++++-
1 files changed, 21 insertions(+), 1 deletions(-)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index 985b36b..e8a5b9b 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -23,7 +23,7 @@ enum {
TAGS_SET = 2
};
-static int append, dry_run, force, keep, update_head_ok, verbosity;
+static int append, dry_run, force, keep, prune, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -42,6 +42,8 @@ static struct option builtin_fetch_options[] = {
"fetch all tags and associated objects", TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
"do not fetch all tags (--no-tags)", TAGS_UNSET),
+ OPT_BOOLEAN('p', "prune", &prune,
+ "prune tracking branches no longer on remote"),
OPT_BOOLEAN(0, "dry-run", &dry_run,
"dry run"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
@@ -489,6 +491,22 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
return ret;
}
+static int prune_refs(struct transport *transport, struct ref *ref_map)
+{
+ int result = 0;
+ struct ref *ref, *stale_refs = get_stale_heads(transport->remote, ref_map);
+ for (ref = stale_refs; ref; ref = ref->next) {
+ if (!dry_run)
+ result |= delete_ref(ref->name, NULL, 0);
+ if (verbosity >= 0)
+ fprintf(stderr, " x %-*s %-*s -> %s\n",
+ SUMMARY_WIDTH, "[deleted]",
+ REFCOL_WIDTH, "(none)", prettify_refname(ref->name));
+ }
+ free_refs(stale_refs);
+ return 0;
+}
+
static int add_existing(const char *refname, const unsigned char *sha1,
int flag, void *cbdata)
{
@@ -613,6 +631,8 @@ static int do_fetch(struct transport *transport,
free_refs(ref_map);
return 1;
}
+ if (prune)
+ prune_refs(transport, ref_map);
free_refs(ref_map);
/* if neither --no-tags nor --tags was specified, do automated tag
--
1.6.4.2
^ permalink raw reply related
* [PATCH/RFC 2/3] builtin-fetch: add --dry-run option
From: Jay Soffian @ 2009-11-06 5:10 UTC (permalink / raw)
To: git; +Cc: Jay Soffian
In-Reply-To: <1257484241-27219-2-git-send-email-jaysoffian@gmail.com>
Teach fetch --dry-run. Unfortunately OPT__DRY_RUN() cannot be used as fetch
already uses "-n" for something else.
---
builtin-fetch.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index cb48c57..985b36b 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -23,7 +23,7 @@ enum {
TAGS_SET = 2
};
-static int append, force, keep, update_head_ok, verbosity;
+static int append, dry_run, force, keep, update_head_ok, verbosity;
static int tags = TAGS_DEFAULT;
static const char *depth;
static const char *upload_pack;
@@ -42,6 +42,8 @@ static struct option builtin_fetch_options[] = {
"fetch all tags and associated objects", TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
"do not fetch all tags (--no-tags)", TAGS_UNSET),
+ OPT_BOOLEAN(0, "dry-run", &dry_run,
+ "dry run"),
OPT_BOOLEAN('k', "keep", &keep, "keep downloaded pack"),
OPT_BOOLEAN('u', "update-head-ok", &update_head_ok,
"allow updating of HEAD ref"),
@@ -178,6 +180,8 @@ static int s_update_ref(const char *action,
char *rla = getenv("GIT_REFLOG_ACTION");
static struct ref_lock *lock;
+ if (dry_run)
+ return 0;
if (!rla)
rla = default_rla.buf;
snprintf(msg, sizeof(msg), "%s: %s", rla, action);
@@ -303,7 +307,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
char note[1024];
const char *what, *kind;
struct ref *rm;
- char *url, *filename = git_path("FETCH_HEAD");
+ char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
fp = fopen(filename, "a");
if (!fp)
@@ -586,7 +590,7 @@ static int do_fetch(struct transport *transport,
die("Don't know how to fetch from %s", transport->url);
/* if not appending, truncate FETCH_HEAD */
- if (!append) {
+ if (!append && !dry_run) {
char *filename = git_path("FETCH_HEAD");
FILE *fp = fopen(filename, "w");
if (!fp)
--
1.6.4.2
^ permalink raw reply related
* [PATCH/RFC 1/3] remote: refactor some logic into get_stale_heads()
From: Jay Soffian @ 2009-11-06 5:10 UTC (permalink / raw)
To: git; +Cc: Jay Soffian
In-Reply-To: <1257484241-27219-1-git-send-email-jaysoffian@gmail.com>
Move the logic in builtin-remote.c which determines which local heads are stale
to remote.c so it can be used by other builtins.
---
builtin-remote.c | 32 ++++++++------------------------
remote.c | 40 ++++++++++++++++++++++++++++++++++++++++
remote.h | 3 +++
3 files changed, 51 insertions(+), 24 deletions(-)
diff --git a/builtin-remote.c b/builtin-remote.c
index 0777dd7..b48267b 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -227,32 +227,10 @@ struct ref_states {
int queried;
};
-static int handle_one_branch(const char *refname,
- const unsigned char *sha1, int flags, void *cb_data)
-{
- struct ref_states *states = cb_data;
- struct refspec refspec;
-
- memset(&refspec, 0, sizeof(refspec));
- refspec.dst = (char *)refname;
- if (!remote_find_tracking(states->remote, &refspec)) {
- struct string_list_item *item;
- const char *name = abbrev_branch(refspec.src);
- /* symbolic refs pointing nowhere were handled already */
- if ((flags & REF_ISSYMREF) ||
- string_list_has_string(&states->tracked, name) ||
- string_list_has_string(&states->new, name))
- return 0;
- item = string_list_append(name, &states->stale);
- item->util = xstrdup(refname);
- }
- return 0;
-}
-
static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
{
struct ref *fetch_map = NULL, **tail = &fetch_map;
- struct ref *ref;
+ struct ref *ref, *stale_refs;
int i;
for (i = 0; i < states->remote->fetch_refspec_nr; i++)
@@ -268,11 +246,17 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
else
string_list_append(abbrev_branch(ref->name), &states->tracked);
}
+ stale_refs = get_stale_heads(states->remote, fetch_map);
+ for (ref = stale_refs; ref; ref = ref->next) {
+ struct string_list_item *item =
+ string_list_append(abbrev_branch(ref->name), &states->stale);
+ item->util = xstrdup(ref->name);
+ }
+ free_refs(stale_refs);
free_refs(fetch_map);
sort_string_list(&states->new);
sort_string_list(&states->tracked);
- for_each_ref(handle_one_branch, states);
sort_string_list(&states->stale);
return 0;
diff --git a/remote.c b/remote.c
index 73d33f2..ee48b49 100644
--- a/remote.c
+++ b/remote.c
@@ -6,6 +6,7 @@
#include "revision.h"
#include "dir.h"
#include "tag.h"
+#include "string-list.h"
static struct refspec s_tag_refspec = {
0,
@@ -1586,3 +1587,42 @@ struct ref *guess_remote_head(const struct ref *head,
return list;
}
+
+struct stale_heads_info {
+ struct remote *remote;
+ struct string_list *ref_names;
+ struct ref **stale_refs_tail;
+};
+
+static int get_stale_heads_cb(const char *refname,
+ const unsigned char *sha1, int flags, void *cb_data)
+{
+ struct stale_heads_info *info = cb_data;
+ struct refspec refspec;
+ memset(&refspec, 0, sizeof(refspec));
+ refspec.dst = (char *)refname;
+ if (!remote_find_tracking(info->remote, &refspec)) {
+ if (!((flags & REF_ISSYMREF) ||
+ string_list_has_string(info->ref_names, refspec.src))) {
+ struct ref *ref = make_linked_ref(refname, &info->stale_refs_tail);
+ hashcpy(ref->new_sha1, sha1);
+ }
+ }
+ return 0;
+}
+
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map)
+{
+ struct ref *ref, *stale_refs = NULL;
+ struct string_list ref_names = { NULL, 0, 0, 0 };
+ struct stale_heads_info info;
+ info.remote = remote;
+ info.ref_names = &ref_names;
+ info.stale_refs_tail = &stale_refs;
+ for (ref = fetch_map; ref; ref = ref->next)
+ string_list_append(ref->name, &ref_names);
+ sort_string_list(&ref_names);
+ for_each_ref(get_stale_heads_cb, &info);
+ string_list_clear(&ref_names, 0);
+ return stale_refs;
+}
diff --git a/remote.h b/remote.h
index 5db8420..d0aba81 100644
--- a/remote.h
+++ b/remote.h
@@ -154,4 +154,7 @@ struct ref *guess_remote_head(const struct ref *head,
const struct ref *refs,
int all);
+/* Return refs which no longer exist on remote */
+struct ref *get_stale_heads(struct remote *remote, struct ref *fetch_map);
+
#endif
--
1.6.4.2
^ permalink raw reply related
* [PATCH/RFC 0/3] teach fetch --prune
From: Jay Soffian @ 2009-11-06 5:10 UTC (permalink / raw)
To: git; +Cc: Jay Soffian
This is just a start so I can get some feedback. Some things still missing:
1) "git remote prune <remote>" calls warn_dangling_symref(), but
"git fetch --prune" does not. I ran out of time tonight to refactor
warn_dangling_symref() to do something more intelligent than just spew to
stdout (which doesn't get along with fetch, which spews to stderr...).
2) Perhaps "git remote update --prune" should be refactored to call
"git fetch --prune". If so, then fetch should gain a "--prune-only" option
so that "git remote prune" can just call "got fetch --prune-only".
3) Perhaps add a config option for users who wish to prune by default.
Thoughts, comments, flames?
Jay Soffian (3):
remote: refactor some logic into get_stale_heads()
builtin-fetch: add --dry-run option
builtin-fetch: add --prune option
builtin-fetch.c | 30 +++++++++++++++++++++++++++---
builtin-remote.c | 32 ++++++++------------------------
remote.c | 40 ++++++++++++++++++++++++++++++++++++++++
remote.h | 3 +++
4 files changed, 78 insertions(+), 27 deletions(-)
^ permalink raw reply
* Re: Preserving branches after merging on ancestor
From: Jonathan Nieder @ 2009-11-06 5:03 UTC (permalink / raw)
To: Björn Steinbrink; +Cc: Richard Lee, git
In-Reply-To: <20091106021038.GA27206@atjola.homenet>
Björn Steinbrink wrote:
> For example in git.git, I can do "git log --first-parent
> ..origin/master" to get a high-level log of what happened. And then I
> might see commit b7eb912b0, which is "Merge branch ja/fetch-doc". So I
> know "OK, there were some doc updates", without having to crawl through
> the individual commits.
Yep, fast-forward merges do ruin the --first-parent log. Thanks for
the reminder.
>> Of course, these things are a matter of taste. I just wanted to
>> explain why a fast-forward could at least sometimes be the right
>> result from merging a topic branch (and why, in practice, some people
>> never end up needing to use --no-ff).
>
> Sure, fast-forwards can be the right thing, e.g. when you have a
> (possibly useless) branch head "master" that you update by pulling. In
> such a case merge commits would only lead to useless clutter.
I hope this use case becomes less important as git’s UI improves. To
track unmodified upstream sources, a simple 'git checkout' to get
up-to-date is much simpler, except that "git branch" does not display
the current branch any more. Using 'git pull' for the daily update
makes for a distractingly merge-heavy history once one has commits of
one’s own.
A similar use case won’t disappear: asking someone else to resolve a
merge for you and pulling the result.
For both these tasks, --ff-only might give better behavior.
In other cases, I would guess some people would always want --no-ff
and others never. Apparently, there is a configuration option to
support this: add a line "mergeoptions = --no-ff" (or "mergeoptions =
--ff") to a [branch "master"] section in .git/config or ~/.gitconfig.
> But
> Richard wants to see where topic branches got merged (to be still able
> to see what got merged in the future), and yeah, that's a matter of
> taste. But you argued that using --no-ff would "[miss] some of the main
> benefits of feature branches", which is simply not true.
I spoke imprecisely; I should have said that if most merges are
candidates for fast-forwarding, this suggests feature branches are not
being used in the best way, and --no-ff just makes that situation more
tolerable.
Then your response pushed me towards the question of whether --no-ff
is a good idea in general, and I got distracted. :) Sorry for the
confusion, and thanks for the insights.
Regards,
Jonathan
^ permalink raw reply
* suggestions for local configs?
From: Tim Rupp @ 2009-11-06 3:11 UTC (permalink / raw)
To: git
Hi list, I'm wrestling with a question and figured that someone on the
list may have some suggestions that have worked for them.
I have a piece of software that has default and local configuration
files. The default files ship with the tarball. The local files are
copied over from the default folder during installation and can be
modified for a particular install.
I clone my source repo on my test and prod systems, but have gotten in
the bad habit of versioning the local configuration files. My (albeit
pathetic) excuse is that when I test the code I may accidentally dork
with the local config files and need to revert back to the correct ones.
At the same time though, I do want to version said local configs in
something so that if changes are made and they need to be backed out, it
can be done and there is the commit log that keeps track of what changed.
So the question is
- Can anyone suggest good ways of setting up git to track both the code
and local configs without making a whole new repository (code repo and
code config repo)
If not, any other suggestions are welcome and I'll consider how best to
make them work in my environment.
I've briefly skimmed through the pro git book online and considered sub
modules and sub-tree merging, but the kicker is that I may need to push
the whole kit-n-kaboodle master repo to remote git servers and those two
approaches sound hairy.
Any help is appreciated.
Thanks,
Tim
^ permalink raw reply
* Re: Preserving branches after merging on ancestor
From: Björn Steinbrink @ 2009-11-06 2:10 UTC (permalink / raw)
To: Jonathan Nieder; +Cc: Richard Lee, git
In-Reply-To: <20091106010947.GB4425@progeny.tock>
On 2009.11.05 19:09:48 -0600, Jonathan Nieder wrote:
> Björn Steinbrink wrote:
>
> > I guess Richard took the "branch topic1, merge topic1, branch topic2,
> > merge topic2" thing just as an example because that ends up with two
> > fast-forwards.
>
> Hmm, I found Richard’s example pretty realistic. I used to work like
> that, and I don’t think I am the only one.
>
> > And your example _still_ has such a fast-forward.
>
> Yep, if you really want to avoid fast-forwards, please use "--no-ff"!
>
> But what I was trying to make clear was that in some workflows, the
> fast-forwards are not so harmful. They even make the history a little
> cleaner (easier to read and understand).
>
> > Instead of:
> >
> > A---B---C---D---E (topic2) (master)
> > \
> > F---G---H (topic1)
> >
> > He wants:
> >
> > F---G---H (topic1)
> > /
> > A---B-----------M (master)
> > \ /
> > C---D---E (topic2)
> >
> > So he can see at which point topic2 got merged. This allows to ask "which
> > commits got merged here" (and for a merge-once topic branch this means:
> > Which commits are related to that topic), by using for example:
> >
> > git log M^1..M^2 # Will show C, D and E
>
> You can get the same information locally even with a fast-forward:
>
> git log master@{1}..master
And after two weeks, you'll dig through the reflog to find the right
entries? Come on... And (as you said yourself below) everyone else
(including yourself in a different clone of that repo) doesn't have that
reflog entry anyway.
> But to someone reading the published history, it is not available.
> Depending on your way of working, this may or may not be reasonable.
>
> Perhaps your merge commit messages contain important information about
> the branch’s overall purpose and provenance, which would be impossible
> if there is no merge commit.
The actual commits that make up the topic should have descriptive enough
commit messages to make extra "why merge this" messages shouldn't be
required. But merge commits provide a way of giving a high-level
overview of the history of a project.
> On the other hand, if the goal is just to present the fact of a merge,
> to explain where a patch falls in the larger scheme of things, then
> how large a chunk of changes I decided to call a feature does not seem
> too important.
For example in git.git, I can do "git log --first-parent
..origin/master" to get a high-level log of what happened. And then I
might see commit b7eb912b0, which is "Merge branch ja/fetch-doc". So I
know "OK, there were some doc updates", without having to crawl through
the individual commits.
And if I decide that for _this_ topic, I care to see what got merged, I
can do: git log b7eb912b0^1..b7eb912b0^2
Had this been a fast-forward, even the --first-parent history would
throw the individual commits at me, giving me less of a high-level
overview.
> Imagine a patch series, cleaning up some ugly code that has been
> bothering me for a while:
>
> base [master] --- A --- B --- C [cleanup]
>
> It looks good, so I merge to master with --no-ff.
>
> base --------- D [master]
> \ /
> A---B---C [cleanup]
>
> Looking at that code inspires me to build a new feature that is much
> easier with the cleaned up version. So I fork a branch from cleanup
> (Or master? Their content is the same, but somehow I choose one) and
> write some patches for the new feature.
>
> base --------- D [master]
> \ /
> A---B---C [cleanup] --- E --- F --- G
>
> It looks good, so I merge.
>
> base --------- D --------- H [master]
> \ / /
> A---B---C---E---F---G
>
> Is this really any easier to read than base---A---B---C---E---F---G?
> In hindsight, was this logically really two series, or is the D commit
> extra cruft?
Choosing "cleanup" as the starting point for an unrelated topic branch
(after all "cleanup" was already merged, so there's absolutely no reason
to base a new topic on it) is wrong. That history looks as if E,F,G was
a second part of the same topic branch.
I'd have done:
E---F---G (topic2)
/ \
0-----------D-----------H (master)
\ /
A---B---C (cleanup)
And then I could do "git log --first-parent master" to see H and D
(high-level view), and "git log H^1..H^2" or "git log D^1..D^2" to get a
low-level view at the merged topics.
Neither of which I could do with "0---A---B---C---E---F---G". With that,
I'd have to manually looking up the start/end points of each topic.
> Almost always, a fast-forward comes from a continuation of this kind,
> since that is what it means for a commit to be the logical commit to
> fork from.
Hm? I don't get that one. The "continuation" would be that you started
the second topic branch from the first topic branch, right? And that
caused the merge to "master" _not_ to be a fast-forward. So I'm somewhat
confused there.
> Of course, these things are a matter of taste. I just wanted to
> explain why a fast-forward could at least sometimes be the right
> result from merging a topic branch (and why, in practice, some people
> never end up needing to use --no-ff).
Sure, fast-forwards can be the right thing, e.g. when you have a
(possibly useless) branch head "master" that you update by pulling. In
such a case merge commits would only lead to useless clutter. But
Richard wants to see where topic branches got merged (to be still able
to see what got merged in the future), and yeah, that's a matter of
taste. But you argued that using --no-ff would "[miss] some of the main
benefits of feature branches", which is simply not true.
Björn
^ permalink raw reply
* Re: Bug in git remote prune?
From: Jay Soffian @ 2009-11-06 1:58 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvdho5t9s.fsf@alter.siamese.dyndns.org>
On Thu, Nov 5, 2009 at 8:36 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Nothing happens because we were told by the refspec not to even look at
> these refs/heads/{next,ghost} refs on the other side.
Gotcha, and that's all you had to say, but I appreciate the long
explanation. :-)
j.
^ 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