Re: [PATCH v2 6/7] rebase: write better reflog messages
Johannes Sixt wrote: I haven't followed the topic closely, but I wonder why there are so many explicit assignments to GIT_REFLOG_ACTION. Is calling set_reflog_action (defined in git-sh-setup) the wrong thing to do? Does this answer your question? set_reflog_action() { if [ -z ${GIT_REFLOG_ACTION:+set} ] then GIT_REFLOG_ACTION=$* export GIT_REFLOG_ACTION fi } -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
Hi, Richard Hansen wrote: --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -82,6 +82,17 @@ to point at the new commit. to the top def_directory,directory of the stored revision. +[[def_committish]]committish (also commit-ish):: + A def_ref,ref pointing to an def_object,object that + can be recursively dereferenced to a + def_commit_object,commit object. Usually I would expect that the string 4d1c565 is not a ref, but the glossary contains a different definition (A 40-byte hex representation of a SHA-1 or ...). I guess we need a shorter name for extended SHA-1 syntax (as described in gitrevisions(7)) that is a little less confusing. Perhaps we can sidestep the issue by saying A parameter pointing to an def_object,object that can be recursively dereferenced to ... since the most common use of commitish is in describing a command's syntax. I'm tempted to go even further and just call that a commit parameter, explaining the more pedantic synonym here --- something like [[def_commitish]]commitish (also commit-ish):: A commandline parameter to a command that requires a def_commit,commit. + The following are all commitishes: an expression (see linkgit:gitrevisions[7]) directly representing a commit object, an expression naming a tag that points to a commit object, a tag that points to a tag that points to a commit, etc. Thanks, Jonathan -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 6/7] rebase: write better reflog messages
Am 6/19/2013 8:09, schrieb Ramkumar Ramachandra: Johannes Sixt wrote: I haven't followed the topic closely, but I wonder why there are so many explicit assignments to GIT_REFLOG_ACTION. Is calling set_reflog_action (defined in git-sh-setup) the wrong thing to do? Does this answer your question? set_reflog_action() { if [ -z ${GIT_REFLOG_ACTION:+set} ] then GIT_REFLOG_ACTION=$* export GIT_REFLOG_ACTION fi } Please don't state the obvious, that does not help. Of course, this does not answer my question. I was rather hinting that it may be wrong to set GIT_REFLOG_ACTION explicitly. I thought that the convention is not to modify GIT_REFLOG_ACTION if it is already set. set_reflog_action does just that. -- Hannes -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 3/3] resolve_ref_unsafe(): close race condition reading loose refs
We read loose references in two steps. The code is roughly: lstat() if error ENOENT: loose ref is missing; look for corresponding packed ref else if S_ISLNK: readlink() if error: report failure else if S_ISDIR: report failure else open() if error: report failure read() The problem is that the first filesystem call, to lstat(), is not atomic with the second filesystem call, to readlink() or open(). Therefore it is possible for another process to change the file between our two calls, for example: * If the other process deletes the file, our second call will fail with ENOENT, which we *should* interpret as loose ref is missing; look for corresponding packed ref. This can arise if the other process is pack-refs; it might have just written a new packed-refs file containing the old contents of the reference then deleted the loose ref. * If the other process changes a symlink into a plain file, our call to readlink() will fail with EINVAL, which we *should* respond to by trying to open() and read() the file. The old code treats the reference as missing in both of these cases, which is incorrect. So instead, handle errors more selectively: if the result of readline()/open() is a failure that is inconsistent with the result of the previous lstat(), then something is fishy. In this case jump back and start over again with a fresh call to lstat(). One race is still possible and undetected: another process could change the file from a regular file into a symlink between the call to lstat and the call to open(). The open() call would silently follow the symlink and not know that something is wrong. This situation could be detected in two ways: * On systems that support O_NOFOLLOW, pass that option to the open(). * On other systems, call fstat() on the fd returned by open() and make sure that it agrees with the stat info from the original lstat(). However, we don't use symlinks anymore, so this situation is unlikely. Moreover, it doesn't appear that treating a symlink as a regular file would have grave consequences; after all, this is exactly how the code handles non-relative symlinks. So this commit leaves that race unaddressed. Note that this solves only the part of the race within resolve_ref_unsafe. In the situation described above, we may still be depending on a cached view of the packed-refs file; that race will be dealt with in a future patch. This problem was reported and diagnosed by Jeff King p...@peff.net, and this solution is derived from his patch. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 28 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/refs.c b/refs.c index 867cf9f..70b2c82 100644 --- a/refs.c +++ b/refs.c @@ -1252,6 +1252,16 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea git_snpath(path, sizeof(path), %s, refname); + /* +* We might have to loop back here to avoid a race +* condition: first we lstat() the file, then we try +* to read it as a link or as a file. But if somebody +* changes the type of the file (file - directory +* - symlink) between the lstat() and reading, then +* we don't want to report that as an error but rather +* try again starting with the lstat(). +*/ + stat_ref: if (lstat(path, st) 0) { if (errno == ENOENT) return handle_missing_loose_ref(refname, sha1, @@ -1263,8 +1273,13 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea /* Follow normalized - ie refs/.. symlinks by hand */ if (S_ISLNK(st.st_mode)) { len = readlink(path, buffer, sizeof(buffer)-1); - if (len 0) - return NULL; + if (len 0) { + if (errno == ENOENT || errno == EINVAL) + /* inconsistent with lstat; retry */ + goto stat_ref; + else + return NULL; + } buffer[len] = 0; if (!prefixcmp(buffer, refs/) !check_refname_format(buffer, 0)) { @@ -1287,8 +1302,13 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea * a ref */ fd = open(path, O_RDONLY); - if (fd 0) - return NULL; + if (fd 0) { + if (errno == ENOENT) + /*
[PATCH v2 2/3] resolve_ref_unsafe(): handle the case of an SHA-1 within loop
There is only one break statement within the loop, which jumps to the code after the loop that handles the case of a file that holds a SHA-1. So move that code from below the loop into the if statement where the break was previously located. This makes the logic flow more local. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/refs.c b/refs.c index ab1f99e..867cf9f 100644 --- a/refs.c +++ b/refs.c @@ -1300,8 +1300,19 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea /* * Is it a symbolic ref? */ - if (prefixcmp(buffer, ref:)) - break; + if (prefixcmp(buffer, ref:)) { + /* +* Please note that FETCH_HEAD has a second +* line containing other data. +*/ + if (get_sha1_hex(buffer, sha1) || + (buffer[40] != '\0' !isspace(buffer[40]))) { + if (flag) + *flag |= REF_ISBROKEN; + return NULL; + } + return refname; + } if (flag) *flag |= REF_ISSYMREF; buf = buffer + 4; @@ -1314,13 +1325,6 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea } refname = strcpy(refname_buffer, buf); } - /* Please note that FETCH_HEAD has a second line containing other data. */ - if (get_sha1_hex(buffer, sha1) || (buffer[40] != '\0' !isspace(buffer[40]))) { - if (flag) - *flag |= REF_ISBROKEN; - return NULL; - } - return refname; } char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int *flag) -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/3] resolve_ref_unsafe(): extract function handle_missing_loose_ref()
The nesting was getting a bit out of hand, and it's about to get worse. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 56 +++- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/refs.c b/refs.c index 42a7e17..ab1f99e 100644 --- a/refs.c +++ b/refs.c @@ -1197,6 +1197,37 @@ static struct ref_entry *get_packed_ref(const char *refname) return find_ref(get_packed_refs(ref_cache), refname); } +/* + * A loose ref file doesn't exist; check for a packed ref. The + * options are forwarded from resolve_safe_unsafe(). + */ +static const char *handle_missing_loose_ref(const char *refname, + unsigned char *sha1, + int reading, + int *flag) +{ + struct ref_entry *entry; + + /* +* The loose reference file does not exist; check for a packed +* reference. +*/ + entry = get_packed_ref(refname); + if (entry) { + hashcpy(sha1, entry-u.value.sha1); + if (flag) + *flag |= REF_ISPACKED; + return refname; + } + /* The reference is not a packed reference, either. */ + if (reading) { + return NULL; + } else { + hashclr(sha1); + return refname; + } +} + const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int reading, int *flag) { int depth = MAXDEPTH; @@ -1222,28 +1253,11 @@ const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int rea git_snpath(path, sizeof(path), %s, refname); if (lstat(path, st) 0) { - struct ref_entry *entry; - - if (errno != ENOENT) + if (errno == ENOENT) + return handle_missing_loose_ref(refname, sha1, + reading, flag); + else return NULL; - /* -* The loose reference file does not exist; -* check for a packed reference. -*/ - entry = get_packed_ref(refname); - if (entry) { - hashcpy(sha1, entry-u.value.sha1); - if (flag) - *flag |= REF_ISPACKED; - return refname; - } - /* The reference is not a packed reference, either. */ - if (reading) { - return NULL; - } else { - hashclr(sha1); - return refname; - } } /* Follow normalized - ie refs/.. symlinks by hand */ -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] sequencer: write useful reflog message for fast-forward
The following command $ git cherry-pick --ff b8bb3f writes the following uninformative message to the reflog cherry-pick Improve it to cherry-pick: fast-forward Avoid hard-coding cherry-pick in fast_forward_to(), so the sequencer is generic enough to support future actions. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- Changes since v1: - fast_forward_to() now takes opts to determine action_name() - strbuf_release() to free memory sequencer.c | 11 --- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sequencer.c b/sequencer.c index ab6f8a7..423c1f5 100644 --- a/sequencer.c +++ b/sequencer.c @@ -270,15 +270,20 @@ static int error_dirty_index(struct replay_opts *opts) } static int fast_forward_to(const unsigned char *to, const unsigned char *from, - int unborn) + int unborn, struct replay_opts *opts) { struct ref_lock *ref_lock; + struct strbuf sb = STRBUF_INIT; + int ret; read_cache(); if (checkout_fast_forward(from, to, 1)) exit(1); /* the callee should have complained already */ ref_lock = lock_any_ref_for_update(HEAD, unborn ? null_sha1 : from, 0); - return write_ref_sha1(ref_lock, to, cherry-pick); + strbuf_addf(sb, %s: fast-forward, action_name(opts)); + ret = write_ref_sha1(ref_lock, to, sb.buf); + strbuf_release(sb); + return ret; } static int do_recursive_merge(struct commit *base, struct commit *next, @@ -523,7 +528,7 @@ static int do_pick_commit(struct commit *commit, struct replay_opts *opts) if (opts-allow_ff ((parent !hashcmp(parent-object.sha1, head)) || (!parent unborn))) -return fast_forward_to(commit-object.sha1, head, unborn); + return fast_forward_to(commit-object.sha1, head, unborn, opts); if (parent parse_commit(parent) 0) /* TRANSLATORS: The first %s will be revert or -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] http.c: don't rewrite the user:passwd string multiple times
On Tue, 18 Jun 2013, Jeff King wrote: But, I don't know if there is any multi-processing happening within the curl library. I don't think curl does any threading; when we are not inside curl_*_perform, there is no curl code running at all (Daniel can correct me if I'm wrong on that). Correct, that's true. The default setup of libcurl never uses any threading at all, everything is done using non-blocking calls and state-machines. There's but a minor exception, so let me describe that case just to be perfectly clear: When you've build libcurl with the threaded resolver backend, libcurl fires up a new thread to resolve host names with during the name resolving phase of a transfer and that thread can then actually continue to run when curl_multi_perform() returns. That's however very isolated, stricly only for name resolving and there should be no way for an application to mess that up. Nothing of what you've discussed in this thread would affect or harm that thread. The biggest impact it tends to have on applications (that aren't following the API properly or assume a little too much) is that it changes the nature of what file descriptors to wait for slightly during the name resolve phase. Some Linux distros ship their default libcurl builds using the threaded resolver. -- / daniel.haxx.se -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 00/12] Fix some reference-related races
Re-roll of mh/ref-races. Thanks to Peff, Junio, and Ramsay for reviewing v1. Changes since v1: * mh/reflife has graduated to master, so this patch series now applies directly to master. * Some trivial constness adjustments were necessary because of 21a6b9fa read-cache: mark cache_entry pointers const * Better explain (in comments and log message) patch 01/12. * In 04/12, access struct lock_file::fd directly instead of keeping a separate copy in struct packed_ref_cache. Please note that this patch series's usage of stat()/fstat() causes breakages under cygwin, pointed out by Ramsay Jones. He has graciously offered to work on this issue. The last patch is still optional--it avoids a little bit of work when rewriting the packed-refs file, but relies on the stat-based freshness check not giving a false negative. Jeff King (2): get_packed_ref_cache: reload packed-refs file when it changes for_each_ref: load all loose refs before packed refs Michael Haggerty (10): repack_without_ref(): split list curation and entry writing pack_refs(): split creation of packed refs and entry writing refs: wrap the packed refs cache in a level of indirection refs: implement simple transactions for the packed-refs file refs: manage lifetime of packed refs cache via reference counting do_for_each_entry(): increment the packed refs cache refcount packed_ref_cache: increment refcount when locked Extract a struct stat_data from cache_entry add a stat_validity struct refs: do not invalidate the packed-refs cache unnecessarily builtin/clone.c| 7 +- builtin/ls-files.c | 12 +- cache.h| 60 -- read-cache.c | 181 ++ refs.c | 314 - refs.h | 27 - 6 files changed, 469 insertions(+), 132 deletions(-) -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 10/12] get_packed_ref_cache: reload packed-refs file when it changes
From: Jeff King p...@peff.net Once we read the packed-refs file into memory, we cache it to save work on future ref lookups. However, our cache may be out of date with respect to what is on disk if another process is simultaneously packing the refs. Normally it is acceptable for us to be a little out of date, since there is no guarantee whether we read the file before or after the simultaneous update. However, there is an important special case: our packed-refs file must be up to date with respect to any loose refs we read. Otherwise, we risk the following race condition: 0. There exists a loose ref refs/heads/master. 1. Process A starts and looks up the ref master. It first checks $GIT_DIR/master, which does not exist. It then loads (and caches) the packed-refs file to see if master exists in it, which it does not. 2. Meanwhile, process B runs pack-refs --all --prune. It creates a new packed-refs file which contains refs/heads/master, and removes the loose copy at $GIT_DIR/refs/heads/master. 3. Process A continues its lookup, and eventually tries $GIT_DIR/refs/heads/master. It sees that the loose ref is missing, and falls back to the packed-refs file. But it examines its cached version, which does not have refs/heads/master. After trying a few other prefixes, it reports master as a non-existent ref. There are many variants (e.g., step 1 may involve process A looking up another ref entirely, so even a fully qualified refname can fail). One of the most interesting ones is if refs/heads/master is already packed. In that case process A will not see it as missing, but rather will report whatever value happened to be in the packed-refs file before process B repacked (which might be an arbitrarily old value). We can fix this by making sure we reload the packed-refs file from disk after looking at any loose refs. That's unacceptably slow, so we can check its stat()-validity as a proxy, and read it only when it appears to have changed. Reading the packed-refs file after performing any loose-ref system calls is sufficient because we know the ordering of the pack-refs process: it always makes sure the newly written packed-refs file is installed into place before pruning any loose refs. As long as those operations by B appear in their executed order to process A, by the time A sees the missing loose ref, the new packed-refs file must be in place. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 21 - 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/refs.c b/refs.c index 6d48b42..d53a172 100644 --- a/refs.c +++ b/refs.c @@ -825,6 +825,9 @@ struct packed_ref_cache { * when it is unlocked. */ struct lock_file *lock; + + /* The metadata from when this packed-refs cache was read */ + struct stat_validity validity; }; /* @@ -859,6 +862,7 @@ static int release_packed_ref_cache(struct packed_ref_cache *packed_refs) { if (!--packed_refs-referrers) { free_ref_entry(packed_refs-root); + stat_validity_clear(packed_refs-validity); free(packed_refs); return 1; } else { @@ -1050,19 +1054,26 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir) */ static struct packed_ref_cache *get_packed_ref_cache(struct ref_cache *refs) { + const char *packed_refs_file; + + if (*refs-name) + packed_refs_file = git_path_submodule(refs-name, packed-refs); + else + packed_refs_file = git_path(packed-refs); + + if (refs-packed + !stat_validity_check(refs-packed-validity, packed_refs_file)) + clear_packed_ref_cache(refs); + if (!refs-packed) { - const char *packed_refs_file; FILE *f; refs-packed = xcalloc(1, sizeof(*refs-packed)); acquire_packed_ref_cache(refs-packed); refs-packed-root = create_dir_entry(refs, , 0, 0); - if (*refs-name) - packed_refs_file = git_path_submodule(refs-name, packed-refs); - else - packed_refs_file = git_path(packed-refs); f = fopen(packed_refs_file, r); if (f) { + stat_validity_update(refs-packed-validity, fileno(f)); read_packed_refs(f, get_ref_dir(refs-packed-root)); fclose(f); } -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 05/12] refs: manage lifetime of packed refs cache via reference counting
In struct packed_ref_cache, keep a count of the number of users of the data structure. Only free the packed ref cache when the reference count goes to zero rather than when the packed ref cache is cleared. This mechanism will be used to prevent the cache data structure from being freed while it is being iterated over. So far, only the reference in struct ref_cache::packed is counted; other users will be adjusted in separate commits. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 39 --- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/refs.c b/refs.c index ad73251..e2e441d 100644 --- a/refs.c +++ b/refs.c @@ -810,6 +810,14 @@ struct packed_ref_cache { struct ref_entry *root; /* +* Count of references to the data structure in this instance, +* including the pointer from ref_cache::packed if any. The +* data will not be freed as long as the reference count is +* nonzero. +*/ + unsigned int referrers; + + /* * Iff the packed-refs file associated with this instance is * currently locked for writing, this points at the associated * lock (which is owned by somebody else). @@ -833,14 +841,38 @@ static struct ref_cache { char name[1]; } ref_cache, *submodule_ref_caches; +/* + * Increment the reference count of *packed_refs. + */ +static void acquire_packed_ref_cache(struct packed_ref_cache *packed_refs) +{ + packed_refs-referrers++; +} + +/* + * Decrease the reference count of *packed_refs. If it goes to zero, + * free *packed_refs and return true; otherwise return false. + */ +static int release_packed_ref_cache(struct packed_ref_cache *packed_refs) +{ + if (!--packed_refs-referrers) { + free_ref_entry(packed_refs-root); + free(packed_refs); + return 1; + } else { + return 0; + } +} + static void clear_packed_ref_cache(struct ref_cache *refs) { if (refs-packed) { - if (refs-packed-lock) + struct packed_ref_cache *packed_refs = refs-packed; + + if (packed_refs-lock) die(internal error: packed-ref cache cleared while locked); - free_ref_entry(refs-packed-root); - free(refs-packed); refs-packed = NULL; + release_packed_ref_cache(packed_refs); } } @@ -1021,6 +1053,7 @@ static struct packed_ref_cache *get_packed_ref_cache(struct ref_cache *refs) FILE *f; refs-packed = xcalloc(1, sizeof(*refs-packed)); + acquire_packed_ref_cache(refs-packed); refs-packed-root = create_dir_entry(refs, , 0, 0); if (*refs-name) packed_refs_file = git_path_submodule(refs-name, packed-refs); -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 03/12] refs: wrap the packed refs cache in a level of indirection
As we know, we can solve any problem in this manner. In this case, the problem is to avoid freeing a packed refs cache while somebody is using it. So add a level of indirection as a prelude to reference-counting the packed refs cache. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 32 ++-- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/refs.c b/refs.c index 9f1a007..373d95b 100644 --- a/refs.c +++ b/refs.c @@ -806,6 +806,10 @@ static int is_refname_available(const char *refname, const char *oldrefname, return 1; } +struct packed_ref_cache { + struct ref_entry *root; +}; + /* * Future: need to be in struct repository * when doing a full libification. @@ -813,7 +817,7 @@ static int is_refname_available(const char *refname, const char *oldrefname, static struct ref_cache { struct ref_cache *next; struct ref_entry *loose; - struct ref_entry *packed; + struct packed_ref_cache *packed; /* * The submodule name, or for the main repo. We allocate * length 1 rather than FLEX_ARRAY so that the main ref_cache @@ -825,7 +829,8 @@ static struct ref_cache { static void clear_packed_ref_cache(struct ref_cache *refs) { if (refs-packed) { - free_ref_entry(refs-packed); + free_ref_entry(refs-packed-root); + free(refs-packed); refs-packed = NULL; } } @@ -996,24 +1001,39 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir) } } -static struct ref_dir *get_packed_refs(struct ref_cache *refs) +/* + * Get the packed_ref_cache for the specified ref_cache, creating it + * if necessary. + */ +static struct packed_ref_cache *get_packed_ref_cache(struct ref_cache *refs) { if (!refs-packed) { const char *packed_refs_file; FILE *f; - refs-packed = create_dir_entry(refs, , 0, 0); + refs-packed = xcalloc(1, sizeof(*refs-packed)); + refs-packed-root = create_dir_entry(refs, , 0, 0); if (*refs-name) packed_refs_file = git_path_submodule(refs-name, packed-refs); else packed_refs_file = git_path(packed-refs); f = fopen(packed_refs_file, r); if (f) { - read_packed_refs(f, get_ref_dir(refs-packed)); + read_packed_refs(f, get_ref_dir(refs-packed-root)); fclose(f); } } - return get_ref_dir(refs-packed); + return refs-packed; +} + +static struct ref_dir *get_packed_ref_dir(struct packed_ref_cache *packed_ref_cache) +{ + return get_ref_dir(packed_ref_cache-root); +} + +static struct ref_dir *get_packed_refs(struct ref_cache *refs) +{ + return get_packed_ref_dir(get_packed_ref_cache(refs)); } void add_packed_ref(const char *refname, const unsigned char *sha1) -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 07/12] packed_ref_cache: increment refcount when locked
Increment the packed_ref_cache reference count while it is locked to prevent its being freed. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/refs.c b/refs.c index d90f487..6d48b42 100644 --- a/refs.c +++ b/refs.c @@ -820,7 +820,9 @@ struct packed_ref_cache { /* * Iff the packed-refs file associated with this instance is * currently locked for writing, this points at the associated -* lock (which is owned by somebody else). +* lock (which is owned by somebody else). The referrer count +* is also incremented when the file is locked and decremented +* when it is unlocked. */ struct lock_file *lock; }; @@ -2096,6 +2098,8 @@ int lock_packed_refs(struct lock_file *lock, int flags) /* Read the current packed-refs while holding the lock: */ packed_ref_cache = get_packed_ref_cache(ref_cache); packed_ref_cache-lock = lock; + /* Increment the reference count to prevent it from being freed: */ + acquire_packed_ref_cache(packed_ref_cache); return 0; } @@ -2116,6 +2120,7 @@ int commit_packed_refs(void) if (commit_lock_file(packed_ref_cache-lock)) error = -1; packed_ref_cache-lock = NULL; + release_packed_ref_cache(packed_ref_cache); return error; } @@ -2128,6 +2133,7 @@ void rollback_packed_refs(void) die(internal error: packed-refs not locked); rollback_lock_file(packed_ref_cache-lock); packed_ref_cache-lock = NULL; + release_packed_ref_cache(packed_ref_cache); clear_packed_ref_cache(ref_cache); } -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 09/12] add a stat_validity struct
It can sometimes be useful to know whether a path in the filesystem has been updated without going to the work of opening and re-reading its content. We trust the stat() information on disk already to handle index updates, and we can use the same trick here. This patch introduces a stat_validity struct which encapsulates the concept of checking the stat-freshness of a file. It is implemented on top of struct stat_data to reuse the logic about which stat entries to trust for a particular platform, but hides the complexity behind two simple functions: check and update. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- cache.h | 27 +++ read-cache.c | 30 ++ 2 files changed, 57 insertions(+) diff --git a/cache.h b/cache.h index f158fed..50f33db 100644 --- a/cache.h +++ b/cache.h @@ -1360,4 +1360,31 @@ int checkout_fast_forward(const unsigned char *from, int sane_execvp(const char *file, char *const argv[]); +/* + * A struct to encapsulate the concept of whether a file has changed + * since we last checked it. This uses criteria similar to those used + * for the index. + */ +struct stat_validity { + struct stat_data *sd; +}; + +void stat_validity_clear(struct stat_validity *sv); + +/* + * Returns 1 if the path is a regular file (or a symlink to a regular + * file) and matches the saved stat_validity, 0 otherwise. A missing + * or inaccessible file is considered a match if the struct was just + * initialized, or if the previous update found an inaccessible file. + */ +int stat_validity_check(struct stat_validity *sv, const char *path); + +/* + * Update the stat_validity from a file opened at descriptor fd. If + * the file is missing, inaccessible, or not a regular file, then + * future calls to stat_validity_check will match iff one of those + * conditions continues to be true. + */ +void stat_validity_update(struct stat_validity *sv, int fd); + #endif /* CACHE_H */ diff --git a/read-cache.c b/read-cache.c index 5660b37..b15bc09 100644 --- a/read-cache.c +++ b/read-cache.c @@ -1950,3 +1950,33 @@ void *read_blob_data_from_index(struct index_state *istate, const char *path, un *size = sz; return data; } + +void stat_validity_clear(struct stat_validity *sv) +{ + free(sv-sd); + sv-sd = NULL; +} + +int stat_validity_check(struct stat_validity *sv, const char *path) +{ + struct stat st; + + if (stat(path, st) 0) + return sv-sd == NULL; + if (!sv-sd) + return 0; + return S_ISREG(st.st_mode) !match_stat_data(sv-sd, st); +} + +void stat_validity_update(struct stat_validity *sv, int fd) +{ + struct stat st; + + if (fstat(fd, st) 0 || !S_ISREG(st.st_mode)) + stat_validity_clear(sv); + else { + if (!sv-sd) + sv-sd = xcalloc(1, sizeof(struct stat_data)); + fill_stat_data(sv-sd, st); + } +} -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 02/12] pack_refs(): split creation of packed refs and entry writing
Split pack_refs() into multiple passes: * Iterate over loose refs. For each one that can be turned into a packed ref, create a corresponding entry in the packed refs cache. * Write the packed refs to the packed-refs file. This change isolates the mutation of the packed-refs file to a single place. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 48 ++-- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/refs.c b/refs.c index 1184b99..9f1a007 100644 --- a/refs.c +++ b/refs.c @@ -2023,35 +2023,50 @@ struct ref_to_prune { struct pack_refs_cb_data { unsigned int flags; + struct ref_dir *packed_refs; struct ref_to_prune *ref_to_prune; - int fd; }; -static int pack_one_ref(struct ref_entry *entry, void *cb_data) +/* + * An each_ref_entry_fn that is run over loose references only. If + * the loose reference can be packed, add an entry in the packed ref + * cache. If the reference should be pruned, also add it to + * ref_to_prune in the pack_refs_cb_data. + */ +static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data) { struct pack_refs_cb_data *cb = cb_data; enum peel_status peel_status; + struct ref_entry *packed_entry; int is_tag_ref = !prefixcmp(entry-name, refs/tags/); - /* ALWAYS pack refs that were already packed or are tags */ - if (!(cb-flags PACK_REFS_ALL) !is_tag_ref - !(entry-flag REF_ISPACKED)) + /* ALWAYS pack tags */ + if (!(cb-flags PACK_REFS_ALL) !is_tag_ref) return 0; /* Do not pack symbolic or broken refs: */ if ((entry-flag REF_ISSYMREF) || !ref_resolves_to_object(entry)) return 0; + /* Add a packed ref cache entry equivalent to the loose entry. */ peel_status = peel_entry(entry, 1); if (peel_status != PEEL_PEELED peel_status != PEEL_NON_TAG) die(internal error peeling reference %s (%s), entry-name, sha1_to_hex(entry-u.value.sha1)); - write_packed_entry(cb-fd, entry-name, entry-u.value.sha1, - peel_status == PEEL_PEELED ? - entry-u.value.peeled : NULL); + packed_entry = find_ref(cb-packed_refs, entry-name); + if (packed_entry) { + /* Overwrite existing packed entry with info from loose entry */ + packed_entry-flag = REF_ISPACKED | REF_KNOWS_PEELED; + hashcpy(packed_entry-u.value.sha1, entry-u.value.sha1); + } else { + packed_entry = create_ref_entry(entry-name, entry-u.value.sha1, + REF_ISPACKED | REF_KNOWS_PEELED, 0); + add_ref(cb-packed_refs, packed_entry); + } + hashcpy(packed_entry-u.value.peeled, entry-u.value.peeled); - /* If the ref was already packed, there is no need to prune it. */ - if ((cb-flags PACK_REFS_PRUNE) !(entry-flag REF_ISPACKED)) { + /* Schedule the loose reference for pruning if requested. */ + if ((cb-flags PACK_REFS_PRUNE)) { int namelen = strlen(entry-name) + 1; struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen); hashcpy(n-sha1, entry-u.value.sha1); @@ -2118,16 +2133,21 @@ static struct lock_file packlock; int pack_refs(unsigned int flags) { struct pack_refs_cb_data cbdata; + int fd; memset(cbdata, 0, sizeof(cbdata)); cbdata.flags = flags; - cbdata.fd = hold_lock_file_for_update(packlock, git_path(packed-refs), - LOCK_DIE_ON_ERROR); + fd = hold_lock_file_for_update(packlock, git_path(packed-refs), + LOCK_DIE_ON_ERROR); + cbdata.packed_refs = get_packed_refs(ref_cache); - write_or_die(cbdata.fd, PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER)); + do_for_each_entry_in_dir(get_loose_refs(ref_cache), 0, +pack_if_possible_fn, cbdata); + + write_or_die(fd, PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER)); + do_for_each_entry_in_dir(cbdata.packed_refs, 0, write_packed_entry_fn, fd); - do_for_each_entry(ref_cache, , pack_one_ref, cbdata); if (commit_lock_file(packlock) 0) die_errno(unable to overwrite old ref-pack file); prune_refs(cbdata.ref_to_prune); -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 06/12] do_for_each_entry(): increment the packed refs cache refcount
This function calls a user-supplied callback function which could do something that causes the packed refs cache to be invalidated. So acquire a reference count on the data structure to prevent our copy from being freed while we are iterating over it. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/refs.c b/refs.c index e2e441d..d90f487 100644 --- a/refs.c +++ b/refs.c @@ -1587,10 +1587,12 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname) static int do_for_each_entry(struct ref_cache *refs, const char *base, each_ref_entry_fn fn, void *cb_data) { - struct ref_dir *packed_dir = get_packed_refs(refs); + struct packed_ref_cache *packed_ref_cache = get_packed_ref_cache(refs); + struct ref_dir *packed_dir = get_packed_ref_dir(packed_ref_cache); struct ref_dir *loose_dir = get_loose_refs(refs); int retval = 0; + acquire_packed_ref_cache(packed_ref_cache); if (base *base) { packed_dir = find_containing_dir(packed_dir, base, 0); loose_dir = find_containing_dir(loose_dir, base, 0); @@ -1611,6 +1613,7 @@ static int do_for_each_entry(struct ref_cache *refs, const char *base, loose_dir, 0, fn, cb_data); } + release_packed_ref_cache(packed_ref_cache); return retval; } -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 01/12] repack_without_ref(): split list curation and entry writing
The repack_without_ref() function first removes the deleted ref from the internal packed-refs list, then writes the packed-refs list to disk, omitting any broken or stale entries. This patch splits that second step into multiple passes: * collect the list of refnames that should be deleted from packed_refs * delete those refnames from the cache * write the remainder to the packed-refs file The purpose of this change is to make the write the remainder part reusable. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 62 ++ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/refs.c b/refs.c index 42a7e17..1184b99 100644 --- a/refs.c +++ b/refs.c @@ -1998,6 +1998,23 @@ static void write_packed_entry(int fd, char *refname, unsigned char *sha1, } } +/* + * An each_ref_entry_fn that writes the entry to a packed-refs file. + */ +static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data) +{ + int *fd = cb_data; + enum peel_status peel_status = peel_entry(entry, 0); + + if (peel_status != PEEL_PEELED peel_status != PEEL_NON_TAG) + error(internal error: %s is not a valid packed reference!, + entry-name); + write_packed_entry(*fd, entry-name, entry-u.value.sha1, + peel_status == PEEL_PEELED ? + entry-u.value.peeled : NULL); + return 0; +} + struct ref_to_prune { struct ref_to_prune *next; unsigned char sha1[20]; @@ -2117,14 +2134,25 @@ int pack_refs(unsigned int flags) return 0; } -static int repack_ref_fn(struct ref_entry *entry, void *cb_data) +/* + * If entry is no longer needed in packed-refs, add it to the string + * list pointed to by cb_data. Reasons for deleting entries: + * + * - Entry is broken. + * - Entry is overridden by a loose ref. + * - Entry does not point at a valid object. + * + * In the first and third cases, also emit an error message because these + * are indications of repository corruption. + */ +static int curate_packed_ref_fn(struct ref_entry *entry, void *cb_data) { - int *fd = cb_data; - enum peel_status peel_status; + struct string_list *refs_to_delete = cb_data; if (entry-flag REF_ISBROKEN) { /* This shouldn't happen to packed refs. */ error(%s is broken!, entry-name); + string_list_append(refs_to_delete, entry-name); return 0; } if (!has_sha1_file(entry-u.value.sha1)) { @@ -2134,7 +2162,7 @@ static int repack_ref_fn(struct ref_entry *entry, void *cb_data) if (read_ref_full(entry-name, sha1, 0, flags)) /* We should at least have found the packed ref. */ die(Internal error); - if ((flags REF_ISSYMREF) || !(flags REF_ISPACKED)) + if ((flags REF_ISSYMREF) || !(flags REF_ISPACKED)) { /* * This packed reference is overridden by a * loose reference, so it is OK that its value @@ -2143,9 +2171,11 @@ static int repack_ref_fn(struct ref_entry *entry, void *cb_data) * collected. For this purpose we don't even * care whether the loose reference itself is * invalid, broken, symbolic, etc. Silently -* omit the packed reference from the output. +* remove the packed reference. */ + string_list_append(refs_to_delete, entry-name); return 0; + } /* * There is no overriding loose reference, so the fact * that this reference doesn't refer to a valid object @@ -2154,14 +2184,10 @@ static int repack_ref_fn(struct ref_entry *entry, void *cb_data) * the output. */ error(%s does not point to a valid object!, entry-name); + string_list_append(refs_to_delete, entry-name); return 0; } - peel_status = peel_entry(entry, 0); - write_packed_entry(*fd, entry-name, entry-u.value.sha1, - peel_status == PEEL_PEELED ? - entry-u.value.peeled : NULL); - return 0; } @@ -2169,6 +2195,8 @@ static int repack_without_ref(const char *refname) { int fd; struct ref_dir *packed; + struct string_list refs_to_delete = STRING_LIST_INIT_DUP; + struct string_list_item *ref_to_delete; if (!get_packed_ref(refname)) return 0; /* refname does not exist in packed refs */ @@ -2180,7 +2208,8 @@ static int repack_without_ref(const char *refname) } clear_packed_ref_cache(ref_cache); packed = get_packed_refs(ref_cache); -
[PATCH v2 08/12] Extract a struct stat_data from cache_entry
Add public functions fill_stat_data() and match_stat_data() to work with it. This infrastructure will later be used to check the validity of other types of file. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- builtin/ls-files.c | 12 +++-- cache.h| 33 +--- read-cache.c | 151 + 3 files changed, 116 insertions(+), 80 deletions(-) diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 2202072..6a0730f 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -165,11 +165,13 @@ static void show_ce_entry(const char *tag, struct cache_entry *ce) } write_name(ce-name, ce_namelen(ce)); if (debug_mode) { - printf( ctime: %d:%d\n, ce-ce_ctime.sec, ce-ce_ctime.nsec); - printf( mtime: %d:%d\n, ce-ce_mtime.sec, ce-ce_mtime.nsec); - printf( dev: %d\tino: %d\n, ce-ce_dev, ce-ce_ino); - printf( uid: %d\tgid: %d\n, ce-ce_uid, ce-ce_gid); - printf( size: %d\tflags: %x\n, ce-ce_size, ce-ce_flags); + struct stat_data *sd = ce-ce_stat_data; + + printf( ctime: %d:%d\n, sd-sd_ctime.sec, sd-sd_ctime.nsec); + printf( mtime: %d:%d\n, sd-sd_mtime.sec, sd-sd_mtime.nsec); + printf( dev: %d\tino: %d\n, sd-sd_dev, sd-sd_ino); + printf( uid: %d\tgid: %d\n, sd-sd_uid, sd-sd_gid); + printf( size: %d\tflags: %x\n, sd-sd_size, ce-ce_flags); } } diff --git a/cache.h b/cache.h index 820aa05..f158fed 100644 --- a/cache.h +++ b/cache.h @@ -119,15 +119,19 @@ struct cache_time { unsigned int nsec; }; +struct stat_data { + struct cache_time sd_ctime; + struct cache_time sd_mtime; + unsigned int sd_dev; + unsigned int sd_ino; + unsigned int sd_uid; + unsigned int sd_gid; + unsigned int sd_size; +}; + struct cache_entry { - struct cache_time ce_ctime; - struct cache_time ce_mtime; - unsigned int ce_dev; - unsigned int ce_ino; + struct stat_data ce_stat_data; unsigned int ce_mode; - unsigned int ce_uid; - unsigned int ce_gid; - unsigned int ce_size; unsigned int ce_flags; unsigned int ce_namelen; unsigned char sha1[20]; @@ -511,6 +515,21 @@ extern int limit_pathspec_to_literal(void); #define HASH_FORMAT_CHECK 2 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags); extern int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned flags); + +/* + * Record to sd the data from st that we use to check whether a file + * might have changed. + */ +extern void fill_stat_data(struct stat_data *sd, struct stat *st); + +/* + * Return 0 if st is consistent with a file not having been changed + * since sd was filled. If there are differences, return a + * combination of MTIME_CHANGED, CTIME_CHANGED, OWNER_CHANGED, + * INODE_CHANGED, and DATA_CHANGED. + */ +extern int match_stat_data(const struct stat_data *sd, struct stat *st); + extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); #define REFRESH_REALLY 0x0001 /* ignore_valid */ diff --git a/read-cache.c b/read-cache.c index 5e30746..5660b37 100644 --- a/read-cache.c +++ b/read-cache.c @@ -67,6 +67,61 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE); } +void fill_stat_data(struct stat_data *sd, struct stat *st) +{ + sd-sd_ctime.sec = (unsigned int)st-st_ctime; + sd-sd_mtime.sec = (unsigned int)st-st_mtime; + sd-sd_ctime.nsec = ST_CTIME_NSEC(*st); + sd-sd_mtime.nsec = ST_MTIME_NSEC(*st); + sd-sd_dev = st-st_dev; + sd-sd_ino = st-st_ino; + sd-sd_uid = st-st_uid; + sd-sd_gid = st-st_gid; + sd-sd_size = st-st_size; +} + +int match_stat_data(const struct stat_data *sd, struct stat *st) +{ + int changed = 0; + + if (sd-sd_mtime.sec != (unsigned int)st-st_mtime) + changed |= MTIME_CHANGED; + if (trust_ctime check_stat + sd-sd_ctime.sec != (unsigned int)st-st_ctime) + changed |= CTIME_CHANGED; + +#ifdef USE_NSEC + if (check_stat sd-sd_mtime.nsec != ST_MTIME_NSEC(*st)) + changed |= MTIME_CHANGED; + if (trust_ctime check_stat + sd-sd_ctime.nsec != ST_CTIME_NSEC(*st)) + changed |= CTIME_CHANGED; +#endif + + if (check_stat) { + if (sd-sd_uid != (unsigned int) st-st_uid || + sd-sd_gid != (unsigned int) st-st_gid) + changed |= OWNER_CHANGED; + if (sd-sd_ino != (unsigned int) st-st_ino) + changed |= INODE_CHANGED; + } + +#ifdef USE_STDEV + /* +* st_dev breaks on network
[PATCH v2 04/12] refs: implement simple transactions for the packed-refs file
Handle simple transactions for the packed-refs file at the packed_ref_cache level via new functions lock_packed_refs(), commit_packed_refs(), and rollback_packed_refs(). Only allow the packed ref cache to be modified (via add_packed_ref()) while the packed refs file is locked. Change clone to add the new references within a transaction. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- builtin/clone.c | 7 - refs.c | 83 ++--- refs.h | 27 +-- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/builtin/clone.c b/builtin/clone.c index 66bff57..b0c000a 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -489,17 +489,22 @@ static struct ref *wanted_peer_refs(const struct ref *refs, return local_refs; } +static struct lock_file packed_refs_lock; + static void write_remote_refs(const struct ref *local_refs) { const struct ref *r; + lock_packed_refs(packed_refs_lock, LOCK_DIE_ON_ERROR); + for (r = local_refs; r; r = r-next) { if (!r-peer_ref) continue; add_packed_ref(r-peer_ref-name, r-old_sha1); } - pack_refs(PACK_REFS_ALL); + if (commit_packed_refs()) + die_errno(unable to overwrite old ref-pack file); } static void write_followtags(const struct ref *refs, const char *msg) diff --git a/refs.c b/refs.c index 373d95b..ad73251 100644 --- a/refs.c +++ b/refs.c @@ -808,6 +808,13 @@ static int is_refname_available(const char *refname, const char *oldrefname, struct packed_ref_cache { struct ref_entry *root; + + /* +* Iff the packed-refs file associated with this instance is +* currently locked for writing, this points at the associated +* lock (which is owned by somebody else). +*/ + struct lock_file *lock; }; /* @@ -829,6 +836,8 @@ static struct ref_cache { static void clear_packed_ref_cache(struct ref_cache *refs) { if (refs-packed) { + if (refs-packed-lock) + die(internal error: packed-ref cache cleared while locked); free_ref_entry(refs-packed-root); free(refs-packed); refs-packed = NULL; @@ -1038,7 +1047,12 @@ static struct ref_dir *get_packed_refs(struct ref_cache *refs) void add_packed_ref(const char *refname, const unsigned char *sha1) { - add_ref(get_packed_refs(ref_cache), + struct packed_ref_cache *packed_ref_cache = + get_packed_ref_cache(ref_cache); + + if (!packed_ref_cache-lock) + die(internal error: packed refs not locked); + add_ref(get_packed_ref_dir(packed_ref_cache), create_ref_entry(refname, sha1, REF_ISPACKED, 1)); } @@ -2035,6 +2049,52 @@ static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data) return 0; } +int lock_packed_refs(struct lock_file *lock, int flags) +{ + struct packed_ref_cache *packed_ref_cache; + + /* Discard the old cache because it might be invalid: */ + clear_packed_ref_cache(ref_cache); + if (hold_lock_file_for_update(lock, git_path(packed-refs), flags) 0) + return -1; + /* Read the current packed-refs while holding the lock: */ + packed_ref_cache = get_packed_ref_cache(ref_cache); + packed_ref_cache-lock = lock; + return 0; +} + +int commit_packed_refs(void) +{ + struct packed_ref_cache *packed_ref_cache = + get_packed_ref_cache(ref_cache); + int error = 0; + + if (!packed_ref_cache-lock) + die(internal error: packed-refs not locked); + write_or_die(packed_ref_cache-lock-fd, +PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER)); + + do_for_each_entry_in_dir(get_packed_ref_dir(packed_ref_cache), +0, write_packed_entry_fn, +packed_ref_cache-lock-fd); + if (commit_lock_file(packed_ref_cache-lock)) + error = -1; + packed_ref_cache-lock = NULL; + return error; +} + +void rollback_packed_refs(void) +{ + struct packed_ref_cache *packed_ref_cache = + get_packed_ref_cache(ref_cache); + + if (!packed_ref_cache-lock) + die(internal error: packed-refs not locked); + rollback_lock_file(packed_ref_cache-lock); + packed_ref_cache-lock = NULL; + clear_packed_ref_cache(ref_cache); +} + struct ref_to_prune { struct ref_to_prune *next; unsigned char sha1[20]; @@ -2153,23 +2213,19 @@ static struct lock_file packlock; int pack_refs(unsigned int flags) { struct pack_refs_cb_data cbdata; - int fd; memset(cbdata, 0, sizeof(cbdata)); cbdata.flags = flags; - fd = hold_lock_file_for_update(packlock, git_path(packed-refs), -
[PATCH v2 11/12] for_each_ref: load all loose refs before packed refs
From: Jeff King p...@peff.net If we are iterating through the refs using for_each_ref (or any of its sister functions), we can get into a race condition with a simultaneous pack-refs --prune that looks like this: 0. We have a large number of loose refs, and a few packed refs. refs/heads/z/foo is loose, with no matching entry in the packed-refs file. 1. Process A starts iterating through the refs. It loads the packed-refs file from disk, then starts lazily traversing through the loose ref directories. 2. Process B, running pack-refs --prune, writes out the new packed-refs file. It then deletes the newly packed refs, including refs/heads/z/foo. 3. Meanwhile, process A has finally gotten to refs/heads/z (it traverses alphabetically). It descends, but finds nothing there. It checks its cached view of the packed-refs file, but it does not mention anything in refs/heads/z/ at all (it predates the new file written by B in step 2). The traversal completes successfully without mentioning refs/heads/z/foo at all (the name, of course, isn't important; but the more refs you have and the farther down the alphabetical list a ref is, the more likely it is to hit the race). If refs/heads/z/foo did exist in the packed refs file at state 0, we would see an entry for it, but it would show whatever sha1 the ref had the last time it was packed (which could be an arbitrarily long time ago). This can be especially dangerous when process A is git prune, as it means our set of reachable tips will be incomplete, and we may erroneously prune objects reachable from that tip (the same thing can happen if repack -ad is used, as it simply drops unreachable objects that are packed). This patch solves it by loading all of the loose refs for our traversal into our in-memory cache, and then refreshing the packed-refs cache. Because a pack-refs writer will always put the new packed-refs file into place before starting the prune, we know that any loose refs we fail to see will either truly be missing, or will have already been put in the packed-refs file by the time we refresh. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 39 +++ 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/refs.c b/refs.c index d53a172..350054c 100644 --- a/refs.c +++ b/refs.c @@ -750,6 +750,21 @@ static int do_for_each_entry_in_dirs(struct ref_dir *dir1, } /* + * Load all of the refs from the dir into our in-memory cache. The hard work + * of loading loose refs is done by get_ref_dir(), so we just need to recurse + * through all of the sub-directories. We do not even need to care about + * sorting, as traversal order does not matter to us. + */ +static void prime_ref_dir(struct ref_dir *dir) +{ + int i; + for (i = 0; i dir-nr; i++) { + struct ref_entry *entry = dir-entries[i]; + if (entry-flag REF_DIR) + prime_ref_dir(get_ref_dir(entry)); + } +} +/* * Return true iff refname1 and refname2 conflict with each other. * Two reference names conflict if one of them exactly matches the * leading components of the other; e.g., foo/bar conflicts with @@ -1600,15 +1615,31 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname) static int do_for_each_entry(struct ref_cache *refs, const char *base, each_ref_entry_fn fn, void *cb_data) { - struct packed_ref_cache *packed_ref_cache = get_packed_ref_cache(refs); - struct ref_dir *packed_dir = get_packed_ref_dir(packed_ref_cache); - struct ref_dir *loose_dir = get_loose_refs(refs); + struct packed_ref_cache *packed_ref_cache; + struct ref_dir *loose_dir; + struct ref_dir *packed_dir; int retval = 0; + /* +* We must make sure that all loose refs are read before accessing the +* packed-refs file; this avoids a race condition in which loose refs +* are migrated to the packed-refs file by a simultaneous process, but +* our in-memory view is from before the migration. get_packed_ref_cache() +* takes care of making sure our view is up to date with what is on +* disk. +*/ + loose_dir = get_loose_refs(refs); + if (base *base) { + loose_dir = find_containing_dir(loose_dir, base, 0); + } + if (loose_dir) + prime_ref_dir(loose_dir); + + packed_ref_cache = get_packed_ref_cache(refs); acquire_packed_ref_cache(packed_ref_cache); + packed_dir = get_packed_ref_dir(packed_ref_cache); if (base *base) { packed_dir = find_containing_dir(packed_dir, base, 0); - loose_dir = find_containing_dir(loose_dir, base, 0); } if (packed_dir loose_dir) { -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message
[PATCH v2 12/12] refs: do not invalidate the packed-refs cache unnecessarily
Now that we keep track of the packed-refs file metadata, we can detect when the packed-refs file has been modified since we last read it, and we do so automatically every time that get_packed_ref_cache() is called. So there is no need to invalidate the cache automatically when lock_packed_refs() is called; usually the old copy will still be valid. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- refs.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/refs.c b/refs.c index 350054c..4b989b0 100644 --- a/refs.c +++ b/refs.c @@ -2133,11 +2133,14 @@ int lock_packed_refs(struct lock_file *lock, int flags) { struct packed_ref_cache *packed_ref_cache; - /* Discard the old cache because it might be invalid: */ - clear_packed_ref_cache(ref_cache); if (hold_lock_file_for_update(lock, git_path(packed-refs), flags) 0) return -1; - /* Read the current packed-refs while holding the lock: */ + /* +* Get the current packed-refs while holding the lock. If the +* packed-refs file has been modified since we last read it, +* this will automatically invalidate the cache and re-read +* the packed-refs file. +*/ packed_ref_cache = get_packed_ref_cache(ref_cache); packed_ref_cache-lock = lock; /* Increment the reference count to prevent it from being freed: */ -- 1.8.3.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Request] Git reset should be able to ignore file permissions
Ok, this is how it looks. If everything is ok, I'm sending it to the ML From 262bdfb5cc84fec7c9b74dc92bb604f9d168ef9a Mon Sep 17 00:00:00 2001 From: Alexander Nestorov alexander...@gmail.com Date: Wed, 19 Jun 2013 09:55:42 +0200 Subject: [PATCH] Add example for reseting based on content changes instead of stat changes --- Documentation/git-reset.txt | 12 1 file changed, 12 insertions(+) diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index a404b47..da639e9 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -289,6 +289,18 @@ $ git reset --keep start3 3 But you can use reset --keep to remove the unwanted commit after you switched to branch2. +Reset only files who's content changed (instead of stat information):: ++ + +$ git update-index --refresh 1 +$ git reset --hard 2 + ++ +1 Make Git realize which files actually changed instead of +checking out all files whether their content changed or only +their mtime changed. +2 Now git reset --hard will checkout only the files that +actually changed. DISCUSSION -- -- 1.8.1.msysgit.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 4/7] status: do not depend on rebase reflog messages
b397ea4 (status: show more info than currently not on any branch, 2013-03-13) attempted to make the output of 'git status' richer in the case of a detached HEAD. Before this patch, with a detached HEAD, we saw: $ git status # Not currently on any branch. But after the patch, we see: $ git checkout v1.8.2 $ git status # HEAD detached at v1.8.2 It works by digging the reflog for the most recent message of the form checkout: moving from to . It then asserts that HEAD and are the same, and displays this message. When they aren't equal, it displays: $ git status # HEAD detached from fe11db so that the user can see where the HEAD was first detached. In case of a rebase [-i] operation in progress, this message depends on the implementation of rebase writing checkout: messages to the reflog, but that is an implementation detail of rebase. To remove this dependency so that rebase can be updated to write better reflog messages, replace this HEAD detached from message with: # rebase in progress; onto $ONTO Changes to the commit object name in the expected output for some of the tests shows that what the test expected status to show during rebase -i was not consistent with the output during a vanilla rebase, which showed on top of what commit the series is being replayed. Now we consistently show something meaningful to the end user. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- t/t7512-status-help.sh | 37 + wt-status.c| 5 - 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index bafa5e7..d6c66d7 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -77,7 +77,7 @@ test_expect_success 'status when rebase in progress before resolving conflicts' ONTO=$(git rev-parse --short HEAD^^) test_must_fail git rebase HEAD^ --onto HEAD^^ cat expected -EOF - # HEAD detached at $ONTO + # rebase in progress; onto $ONTO # You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''. # (fix conflicts and then run git rebase --continue) # (use git rebase --skip to skip this patch) @@ -104,7 +104,7 @@ test_expect_success 'status when rebase in progress before rebase --continue' ' echo three main.txt git add main.txt cat expected -EOF - # HEAD detached at $ONTO + # rebase in progress; onto $ONTO # You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''. # (all conflicts fixed: run git rebase --continue) # @@ -136,7 +136,7 @@ test_expect_success 'status during rebase -i when conflicts unresolved' ' ONTO=$(git rev-parse --short rebase_i_conflicts) test_must_fail git rebase -i rebase_i_conflicts cat expected -EOF - # HEAD detached at $ONTO + # rebase in progress; onto $ONTO # You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''. # (fix conflicts and then run git rebase --continue) # (use git rebase --skip to skip this patch) @@ -162,7 +162,7 @@ test_expect_success 'status during rebase -i after resolving conflicts' ' test_must_fail git rebase -i rebase_i_conflicts git add main.txt cat expected -EOF - # HEAD detached at $ONTO + # rebase in progress; onto $ONTO # You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''. # (all conflicts fixed: run git rebase --continue) # @@ -188,10 +188,9 @@ test_expect_success 'status when rebasing -i in edit mode' ' export FAKE_LINES test_when_finished git rebase --abort ONTO=$(git rev-parse --short HEAD~2) - TGT=$(git rev-parse --short two_rebase_i) git rebase -i HEAD~2 cat expected -EOF - # HEAD detached from $TGT + # rebase in progress; onto $ONTO # You are currently editing a commit while rebasing branch '\''rebase_i_edit'\'' on '\''$ONTO'\''. # (use git commit --amend to amend the current commit) # (use git rebase --continue once you are satisfied with your changes) @@ -216,9 +215,8 @@ test_expect_success 'status when splitting a commit' ' ONTO=$(git rev-parse --short HEAD~3) git rebase -i HEAD~3 git reset HEAD^ - TGT=$(git rev-parse --short HEAD) cat expected -EOF - # HEAD detached at $TGT + # rebase in progress; onto $ONTO # You are currently splitting a commit while rebasing branch '\''split_commit'\'' on '\''$ONTO'\''. # (Once your working directory is clean, run git rebase --continue) # @@ -246,11 +244,10 @@ test_expect_success 'status after editing the last commit with --amend during a export FAKE_LINES
[PATCH v3 0/7] Re-roll rr/rebase-checkout-reflog
So, this is hopefully the final re-roll. [6/7] and [7/7] have updated commit messages and comments describing what this new base_reflog_action is. Also, to prevent breakages with another in-flight topic, the test that Junio contributed to [7/7] uses a different branch name. Thanks. Junio C Hamano (1): t/t7512-status-help: test HEAD detached from Ramkumar Ramachandra (6): wt-status: remove unused field in grab_1st_switch_cbdata t/t2012-checkout-last: test checkout - after a rebase status: do not depend on rebase reflog messages checkout: respect GIT_REFLOG_ACTION rebase: write better reflog messages rebase -i: write better reflog messages builtin/checkout.c| 11 +++--- git-am.sh | 4 +++- git-rebase--am.sh | 7 +++ git-rebase--interactive.sh| 14 + git-rebase.sh | 18 +++-- t/t2012-checkout-last.sh | 34 +++ t/t3404-rebase-interactive.sh | 15 ++ t/t7512-status-help.sh| 47 --- wt-status.c | 7 --- 9 files changed, 123 insertions(+), 34 deletions(-) -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 1/7] t/t7512-status-help: test HEAD detached from
From: Junio C Hamano gits...@pobox.com b397ea (status: show more info than currently not on any branch, 2013-03-13) wanted to make sure that after a checkout to detach HEAD, the user can see where the HEAD was originally detached from. The last test added by that commit to t/status-help shows one example, immediately after HEAD is detached via a checkout. Enhance that test to test the HEAD detached from message is displayed when the user further resets to another commit. Signed-off-by: Junio C Hamano gits...@pobox.com Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- t/t7512-status-help.sh | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh index bf08d4e..bafa5e7 100755 --- a/t/t7512-status-help.sh +++ b/t/t7512-status-help.sh @@ -667,7 +667,7 @@ test_expect_success 'status when cherry-picking after resolving conflicts' ' test_i18ncmp expected actual ' -test_expect_success 'status showing detached from a tag' ' +test_expect_success 'status showing detached at and from a tag' ' test_commit atag tagging git checkout atag cat expected -\EOF @@ -675,6 +675,14 @@ test_expect_success 'status showing detached from a tag' ' nothing to commit (use -u to show untracked files) EOF git status --untracked-files=no actual + test_i18ncmp expected actual + + git reset --hard HEAD^ + cat expected -\EOF + # HEAD detached from atag + nothing to commit (use -u to show untracked files) + EOF + git status --untracked-files=no actual test_i18ncmp expected actual ' -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 2/7] wt-status: remove unused field in grab_1st_switch_cbdata
The struct grab_1st_switch_cbdata has the field found, which is set in grab_1st_switch() when a match is found. This information is redundant and unused by any code. The return value of the function serves to communicate this information anyway. Remove the field. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- wt-status.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/wt-status.c b/wt-status.c index bf84a86..2511270 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1035,7 +1035,6 @@ got_nothing: } struct grab_1st_switch_cbdata { - int found; struct strbuf buf; unsigned char nsha1[20]; }; @@ -1059,7 +1058,6 @@ static int grab_1st_switch(unsigned char *osha1, unsigned char *nsha1, for (end = target; *end *end != '\n'; end++) ; strbuf_add(cb-buf, target, end - target); - cb-found = 1; return 1; } -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 3/7] t/t2012-checkout-last: test checkout - after a rebase
$ git checkout - does not work as expected after a rebase. This is because the reflog records checkout made by rebase as its implementation detail the same way as end-user initiated checkout, and makes it count as the branch that was previously checked out. Add four failing tests documenting this bug: two for a normal rebase, and another two for an interactive rebase. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- t/t2012-checkout-last.sh | 34 ++ 1 file changed, 34 insertions(+) diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh index b44de9d..6ad6edf 100755 --- a/t/t2012-checkout-last.sh +++ b/t/t2012-checkout-last.sh @@ -116,4 +116,38 @@ test_expect_success 'master...' ' test z$(git rev-parse --verify HEAD) = z$(git rev-parse --verify master^) ' +test_expect_failure 'checkout - works after a rebase A' ' + git checkout master + git checkout other + git rebase master + git checkout - + test z$(git symbolic-ref HEAD) = zrefs/heads/master +' + +test_expect_failure 'checkout - works after a rebase A B' ' + git branch moodle master~1 + git checkout master + git checkout other + git rebase master moodle + git checkout - + test z$(git symbolic-ref HEAD) = zrefs/heads/master +' + +test_expect_failure 'checkout - works after a rebase -i A' ' + git checkout master + git checkout other + git rebase -i master + git checkout - + test z$(git symbolic-ref HEAD) = zrefs/heads/master +' + +test_expect_failure 'checkout - works after a rebase -i A B' ' + git branch foodle master~1 + git checkout master + git checkout other + git rebase master foodle + git checkout - + test z$(git symbolic-ref HEAD) = zrefs/heads/master +' + test_done -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 5/7] checkout: respect GIT_REFLOG_ACTION
GIT_REFLOG_ACTION is an environment variable specifying the reflog message to write after an action is completed. Several other commands including merge, reset, and commit respect it. Fix the failing tests in t/checkout-last by making checkout respect it too. You can now expect $ git checkout - to work as expected after any a rebase [-i]. It will also work with any other scripts provided they set an appropriate GIT_REFLOG_ACTION if they internally use git checkout. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- builtin/checkout.c | 11 --- t/t2012-checkout-last.sh | 8 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/builtin/checkout.c b/builtin/checkout.c index f5b50e5..1e2af85 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -587,7 +587,7 @@ static void update_refs_for_switch(const struct checkout_opts *opts, struct branch_info *new) { struct strbuf msg = STRBUF_INIT; - const char *old_desc; + const char *old_desc, *reflog_msg; if (opts-new_branch) { if (opts-new_orphan_branch) { if (opts-new_branch_log !log_all_ref_updates) { @@ -620,8 +620,13 @@ static void update_refs_for_switch(const struct checkout_opts *opts, old_desc = old-name; if (!old_desc old-commit) old_desc = sha1_to_hex(old-commit-object.sha1); - strbuf_addf(msg, checkout: moving from %s to %s, - old_desc ? old_desc : (invalid), new-name); + + reflog_msg = getenv(GIT_REFLOG_ACTION); + if (!reflog_msg) + strbuf_addf(msg, checkout: moving from %s to %s, + old_desc ? old_desc : (invalid), new-name); + else + strbuf_insert(msg, 0, reflog_msg, strlen(reflog_msg)); if (!strcmp(new-name, HEAD) !new-path !opts-force_detach) { /* Nothing to do. */ diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh index 6ad6edf..e7ba8c5 100755 --- a/t/t2012-checkout-last.sh +++ b/t/t2012-checkout-last.sh @@ -116,7 +116,7 @@ test_expect_success 'master...' ' test z$(git rev-parse --verify HEAD) = z$(git rev-parse --verify master^) ' -test_expect_failure 'checkout - works after a rebase A' ' +test_expect_success 'checkout - works after a rebase A' ' git checkout master git checkout other git rebase master @@ -124,7 +124,7 @@ test_expect_failure 'checkout - works after a rebase A' ' test z$(git symbolic-ref HEAD) = zrefs/heads/master ' -test_expect_failure 'checkout - works after a rebase A B' ' +test_expect_success 'checkout - works after a rebase A B' ' git branch moodle master~1 git checkout master git checkout other @@ -133,7 +133,7 @@ test_expect_failure 'checkout - works after a rebase A B' ' test z$(git symbolic-ref HEAD) = zrefs/heads/master ' -test_expect_failure 'checkout - works after a rebase -i A' ' +test_expect_success 'checkout - works after a rebase -i A' ' git checkout master git checkout other git rebase -i master @@ -141,7 +141,7 @@ test_expect_failure 'checkout - works after a rebase -i A' ' test z$(git symbolic-ref HEAD) = zrefs/heads/master ' -test_expect_failure 'checkout - works after a rebase -i A B' ' +test_expect_success 'checkout - works after a rebase -i A B' ' git branch foodle master~1 git checkout master git checkout other -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 6/7] rebase: write better reflog messages
Now that the checkout invoked internally from rebase knows to honor GIT_REFLOG_ACTION, we can start to use it to write a better reflog message when rebase anotherbranch, rebase --onto branch, etc. internally checks out the new fork point. We will write: rebase: checkout master instead of the old rebase The usage semantics of GIT_REFLOG_ACTION have changed; by appending to GIT_REFLOG_ACTION directly, we risk appending to a prebuilt string like rebase: checkout mool from a previous append, when we really intended to append to the string rebase. Solve this problem by introducing a base_reflog_action variable that is different from GIT_REFLOG_ACTION. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- git-am.sh | 4 +++- git-rebase--am.sh | 7 +++ git-rebase.sh | 18 -- 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/git-am.sh b/git-am.sh index 1cf3d1d..74ef9ca 100755 --- a/git-am.sh +++ b/git-am.sh @@ -46,6 +46,8 @@ set_reflog_action am require_work_tree cd_to_toplevel +base_reflog_action=$GIT_REFLOG_ACTION + git var GIT_COMMITTER_IDENT /dev/null || die $(gettext You need to set your committer info first) @@ -884,7 +886,7 @@ did you forget to use 'git add'? fi git commit-tree $tree ${parent:+-p} $parent $dotest/final-commit ) - git update-ref -m $GIT_REFLOG_ACTION: $FIRSTLINE HEAD $commit $parent || + git update-ref -m $base_reflog_action: $FIRSTLINE HEAD $commit $parent || stop_here $this if test -f $dotest/original-commit; then diff --git a/git-rebase--am.sh b/git-rebase--am.sh index 34e3102..7fbeb35 100644 --- a/git-rebase--am.sh +++ b/git-rebase--am.sh @@ -5,11 +5,13 @@ case $action in continue) + GIT_REFLOG_ACTION=$base_reflog_action git am --resolved --resolvemsg=$resolvemsg move_to_original_branch return ;; skip) + GIT_REFLOG_ACTION=$base_reflog_action git am --skip --resolvemsg=$resolvemsg move_to_original_branch return @@ -40,9 +42,11 @@ else rm -f $GIT_DIR/rebased-patches case $head_name in refs/heads/*) + GIT_REFLOG_ACTION=$base_reflog_action: checkout $head_name git checkout -q $head_name ;; *) + GIT_REFLOG_ACTION=$base_reflog_action: checkout $orig_head git checkout -q $orig_head ;; esac @@ -59,6 +63,9 @@ else return $? fi + # always reset GIT_REFLOG_ACTION before calling any external + # scripts; they have no idea about our base_reflog_action + GIT_REFLOG_ACTION=$base_reflog_action git am $git_am_opt --rebasing --resolvemsg=$resolvemsg $GIT_DIR/rebased-patches ret=$? diff --git a/git-rebase.sh b/git-rebase.sh index d0c11a9..6cdf9f8 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -47,6 +47,13 @@ set_reflog_action rebase require_work_tree_exists cd_to_toplevel +# Should contain a base string like rebase (or rebase -i (start)) +# to which a more information like : checkout foom can be appended +# to set the final GIT_REFLOG_ACTION. If you append to +# GIT_REFLOG_ACTION directly, you risk appending to a prebuilt string +# like rebase: checkout mool from a previous append. +base_reflog_action=$GIT_REFLOG_ACTION + LF=' ' ok_to_skip_pre_rebase= @@ -336,7 +343,8 @@ then # Only interactive rebase uses detailed reflog messages if test $type = interactive test $GIT_REFLOG_ACTION = rebase then - GIT_REFLOG_ACTION=rebase -i ($action) + GIT_REFLOG_ACTION=rebase -i ($1) + base_reflog_action=$GIT_REFLOG_ACTION export GIT_REFLOG_ACTION fi fi @@ -543,7 +551,11 @@ then if test -z $force_rebase then # Lazily switch to the target branch if needed... - test -z $switch_to || git checkout $switch_to -- + if test -n $switch_to + then + GIT_REFLOG_ACTION=$base_reflog_action: checkout $switch_to + git checkout $switch_to -- + fi say $(eval_gettext Current branch \$branch_name is up to date.) exit 0 else @@ -568,6 +580,8 @@ test $type = interactive run_specific_rebase # Detach HEAD and reset the tree say $(gettext First, rewinding head to replay your work on top of it...) + +GIT_REFLOG_ACTION=$base_reflog_action: checkout $onto_name git checkout -q $onto^0 || die could not detach HEAD git update-ref ORIG_HEAD $orig_head -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info
[PATCH v3 7/7] rebase -i: write better reflog messages
Now that the checkout invoked internally from rebase -i knows to honor GIT_REFLOG_ACTION, we can start to use it to write a better reflog message when rebase -i anotherbranch, rebase -i --onto branch, etc. internally checks out the new fork point. We will write: rebase -i (start): checkout master instead of the old rebase -i (start) The usage semantics of GIT_REFLOG_ACTION have changed: use base_reflog_action just like in git-rebase.sh. [jc: add rebase-reflog test] Signed-off-by: Ramkumar Ramachandra artag...@gmail.com Signed-off-by: Junio C Hamano gits...@pobox.com --- git-rebase--interactive.sh| 14 ++ t/t3404-rebase-interactive.sh | 15 +++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh index f953d8d..8429c87 100644 --- a/git-rebase--interactive.sh +++ b/git-rebase--interactive.sh @@ -95,12 +95,15 @@ commit_message () { git cat-file commit $1 | sed 1,/^$/d } -orig_reflog_action=$GIT_REFLOG_ACTION +base_reflog_action=$GIT_REFLOG_ACTION comment_for_reflog () { - case $orig_reflog_action in + case $base_reflog_action in + # if GIT_REFLOG_ACTION was set by caller git-rebase, overwrite + # it with rebase -i. ''|rebase*) GIT_REFLOG_ACTION=rebase -i ($1) + base_reflog_action=$GIT_REFLOG_ACTION export GIT_REFLOG_ACTION ;; esac @@ -326,6 +329,7 @@ pick_one_preserving_merges () { if [ $1 != -n ] then # detach HEAD to current parent + GIT_REFLOG_ACTION=$base_reflog_action: checkout $first_parent output git checkout $first_parent 2 /dev/null || die Cannot move HEAD to $first_parent fi @@ -608,10 +612,10 @@ do_next () { newhead=$(git rev-parse HEAD) case $head_name in refs/*) - message=$GIT_REFLOG_ACTION: $head_name onto $onto + message=$base_reflog_action: $head_name onto $onto git update-ref -m $message $head_name $newhead $orig_head git symbolic-ref \ - -m $GIT_REFLOG_ACTION: returning to $head_name \ + -m $base_reflog_action: returning to $head_name \ HEAD $head_name ;; esac { @@ -838,6 +842,7 @@ comment_for_reflog start if test ! -z $switch_to then + GIT_REFLOG_ACTION=$base_reflog_action: checkout $switch_to output git checkout $switch_to -- || die Could not checkout $switch_to fi @@ -981,6 +986,7 @@ has_action $todo || test -d $rewritten || test -n $force_rebase || skip_unnecessary_picks +GIT_REFLOG_ACTION=$base_reflog_action: checkout $onto_name output git checkout $onto || die_abort could not detach HEAD git update-ref ORIG_HEAD $orig_head do_rest diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh index 79e8d3c..f943efa 100755 --- a/t/t3404-rebase-interactive.sh +++ b/t/t3404-rebase-interactive.sh @@ -934,6 +934,21 @@ test_expect_success 'rebase --edit-todo can be used to modify todo' ' test L = $(git cat-file commit HEAD | sed -ne \$p) ' +test_expect_success 'rebase -i produces readable reflog' ' + git reset --hard + git branch -f branch-reflog-test H + git rebase -i --onto I F branch-reflog-test + cat expect -\EOF + rebase -i (start): checkout I + rebase -i (pick): G + rebase -i (pick): H + rebase -i (finish): returning to refs/heads/branch-reflog-test + EOF + tail -n 4 .git/logs/HEAD | + sed -e s/.*// actual + test_cmp expect actual +' + test_expect_success 'rebase -i respects core.commentchar' ' git reset --hard git checkout E^0 -- 1.8.3.1.449.g41b32a4.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Chanel Taschen Online
Chanel Taschen Outlet http://www.onlinechaneltaschenshop.de/ Normalerweise wĆ¼rden Sie brauchen, um eine Chanel Flagship-Store, oder hochwertigen Bereich Shop besuchen, um Chanel Designer-Handtaschen und Taschen zu finden, und zusƤtzlich wĆ¼rden Sie zahlen eine ganz Cent fĆ¼r jeden einzelnen (typisch kostet ca. $ 1.000). GlĆ¼cklicherweise bietet das Internet-Welt eine Menge von Optionen fĆ¼r die Mode-weise Frau zu top-of-the-line-Designer-Taschen zu gĆ¼nstigen prices.Of natĆ¼rlich erhalten, gesprochen hatte Chanel in diesem Fall, so youre immer noch zu zahlen, eine gesunde kosten, aber auch aus einer Handtasche, Sie werden die FƤhigkeit zu erwerben haben nicht eine, sondern zwei oder drei. Weibliche Person, sind Sie sich bewusst gibt es absolut nichts, wie die Design, QualitƤt und Komfort zusƤtzlich eine echte Chanel Handtasche. Trotz allem, was der Zustand des Geistes, gibt es eine Chanel-Handtasche, um eine pfiffige Idee, online zu schauen, um Chanel Handtasche kaufen suit.Its, weil Sie das GefĆ¼hl wirst in der Lage, einige fantastische SchnƤppchen zu finden. Sie nicht auch, weggetragen zu werden, though. Du wirst sie mƶgen zu machen, dass Sie wieder zu erwerben ausschlieĆlich authentischen Chanel und nie die kostengĆ¼nstig gefƤlschte Sachen. Bevor Sie kaufen, schlage ich gerade viele SƤcke kennen zu lernen genau das, was ein authentisches Chanel Handtasche scheint. Dont von jedem Anbieter, die Ihnen einen kaufen komisches GefĆ¼hl. Im Gegensatz zu vielen Herstellern verfĆ¼gbar Design dagegen, und positioniert sie innerhalb emuliert abwerten erscheinen.noch besser zu verhindern, durch die mƶglichen Kunden des Angebots genutzt chanel HandgepƤck billig erworben, den Wert durch einen langwierigen Art von benutzerdefinierten zusammen mit gummierten positioniert hohen QualitƤt. Du'll der Lage sein, zu erkennen, warum chanel kƶnnen kommen, um wƤhrend der Mittelpunkt all den Medien weltweit, ist derjenige, der unnachahmliche Sammlung Unternehmen bietet, wenn es um Kunden geht hervorragend. Es ist ein beliebtes Chanel Taschen Online Shop http://www.onlinechaneltaschenshop.de/ Auf der Internet-Design-Details, um Ihren Lebensstil zu koordinieren kann ein wenig helfen. Sie kƶnnen sehr preiswert sein, obwohl es sicherlich spezialisiert ist, kƶnnen Sie Ihre Art zu erklƤren. Unsere sind wirklich in der Regel oft eine gesĆ¼ndere Merkmale sind daher tatsƤchlich Beweise fĆ¼r einen Widerstand der unbegrenzten Preis um Longchamp store Lieferanten. Um herauszufinden, wie es zu fabelhaften Anzeige von erstaunlichen Geldbƶrsen erscheinen, ist eigentlich keine zusƤtzlichen Kriterien, um die wahre IdentitƤt? Ich mag Ihnen sagen: Es muss eine Zahl Longchamp Taschen Online-Shop sein und auch Handtaschen lernen trotzdem, hallo, was wĆ¼rde kritisieren? Wenn Kauf eine Tasche zu individuellen IdentitƤt, mĆ¼ssen Sie bestimmte Eigenschaften in der Liste oben richten: Farbauswahl, Abmessungen, sowie Musik Brands.Longchamp Geldbeutel kann die Positionierung an der Zeit zu halten, im Grunde zeigt nicht unbedingt nur der Reichtum Erstellen jeder von der Frauen, sondern zusƤtzlich ermƶglichen es, einfach zu sein fĆ¼r die meisten Frauen mehr die erstaunliche, die Art der gal, bot Sie Heimkehr erwarten Sie zu wissen, ob und wann MƤdchen oder vielleicht aufhƶren MƤdchen erlebt die junge Frau in ihr Longchamp Taschen. Fein, legt der Trick in sein smart. Es ist notwendig, sich selbst zu erziehen, welche Investitionen aa viel Geld auf gute Dinge ist sicherlich nicht die besondere Art, um sich stilvoll. Sie sind in der Lage, tatsƤchlich sehen wunderbar mit nicht immer Ihre Taschen leer. Neugierig, wie? Die Lƶsung, die wirklich zweiten geben SƤcke. All diese Frauen, die Sie in jeder beliebigen Einzel-und jede Feier mit einem brandneuen Designer-Handtasche jedes Mal nicht automatisch kaufen? Diejenigen die meiste Zeit. Null von ihnen wollen, es zu akzeptieren, aber die wichtige Tatsache hinter ihnen trƤgt eine andere Handtasche fĆ¼r jede Feier ist, die sie kaufen 2. SƤcke geben. Betrachten Sie es logisch, wenn oder wenn Sie es schaffen, erhalten eine Chanel taschen 2. in einem guten Zustand fĆ¼r die HƤlfte der ursprĆ¼nglichen Kosten zu geben, dann sind die GrĆ¼nde, warum wollen Sie ein Original zu kaufen? Es gibt eine Menge von Web-Seiten auf Linie diesen Tagen, dass und bieten auch kaufen aus zweiter Hand Taschen und auch Moderatoren zwischen Kunden und HƤndlern zusƤtzlich zu werden. Eine einfache Registrierung auf der Spitze dieser Seiten ist alles was man kann, um all die verschiedenen Mƶglichkeiten, sich einen Chanel taschen 2nd Hand auf dem Internet erscheinen! Winterzeit weibliche BerĆ¼hmtheit Platz auf der Oberseite des aufgeblƤhten Daunenmantel, keine Mƶglichkeit, Chanel Taschen kaufen http://www.onlinechaneltaschenshop.de/ diese edle in, nur innerhalb der Hand Handtasche Arme auf zu markieren, mĆ¼ssen stattfinden, um ein KostĆ¼m zu verkaufen, ist zart, sogar eine Ćppigkeit. Deluxe Beutel ist in der Regel Schauspielerin, die wirklich wie eine groĆe Anzahl
Nike Air Max billig
Nike Air Max billig http://www.schuhenzalando.de/nike-air-max Ich habe AusĆ¼bung ca. 3 Jahren und genutzt haben diese tolle Alltag Nike Shox oz Schuhe, die teure Reebok sowie die Damen Adidas Originals Jeremy Scott zigs. Out und auch weg, Entwicklung des Kindes eine groĆe Anzahl von flexiblen Schuhe auf unserem Online-Shop. Weil sie geschehen zu sein Der Nike Shox Schuhe kƶnnen ganz leicht zusammen mit der Vibram Sohle Konstruktion ist 1. Klasse. Neben solchen als eine kleine Layout, fĆ¼hlen unsere robuste auch als der Fokus auf robuste Konstruktion gefunden werden kann, was normal ist fĆ¼r die Marke Nike. Sie kƶnnten wirklich die bequemste MƤdchen, die er bekommen hatte ist bis jetzt gelungen sein. Die Fersenkappe DƤmpfung besonders ist wirklich nĆ¼tzlich, sowie in zahlreichen FƤllen ohne Socken gab es jede Art von Reizung. Leistung smart, sind die Vibram Sohlen grandios. Nie zu federnden, anstatt auch biegsam, bieten das Paar die beste Balance zwischen einem GefĆ¼hl barfuĆ und Bereitstellung Verteidigung gegen gezackten Steinen und auch Glas. Das Schuhwerk scheint genial Ć¼ber das Laufband Maschine zu wie auf BĆ¼rgersteig lief I 2 Meilen mein Favorit ersten Versuch und zusƤtzlich das Kalb nicht tƶtet mich das sehr folgenden Tag. Wenn beim Umgang oder in der es Luftbedarf neunzig Turnschuhe Sie geneigt sein, wirklich das GefĆ¼hl, biegbar sowie sehr viel wohler, wenn Sie erwarten, im Vergleich kƶnnte. Und das heiĆt, Sie kƶnnten auf diejenigen Videospiel konzentrieren, da die Schuhe und Schuhe nike air max danmark weg ein paar aus der ganzen Angst gefĆ¼llt erfĆ¼llen Ihre BedĆ¼rfnisse. Ein gemĆ¼tliches Spiel ist in der Regel zusammen mit fantastische UnterstĆ¼tzung, da die untere Schicht in der Regel entlang der Hilfe in den Boden von allen Basketballspiel Betriebssystem Schuhe bietet eine angenehme sichere neben gepolsterten Outfit. Entsprechende richtigen Griff Ć¼ber der Basis ist nicht schwer dennoch wird hauptsƤchlich Ć¼ber die Ferse hƶher als zu FuĆ vor Ort durch, dass ein groĆer Vertrag mit dem Endergebnis durchsickert wo richtigen Griff ist gehen zu mĆ¼ssen, positioniert. Jetzt kann es regelmƤĆig eine Debatte hinsichtlich betrachten wir feinste kleine Liga Schuhe oder Stiefel oder Schuhe jetzt verfĆ¼gbar sind. Distinctive Menschen haben aa Menge der Moral Ć¼ber die gleiche AbhƤngigkeit von einzelnen Know-how ist es. Nike Air Max gĆ¼nstig http://www.schuhenzalando.de/nike-air-max Flugreisen Max TN, in Wirklichkeit kann es eine Basketball-Schuhe, peut groĆe KreativitƤt aus footing.Though mit Ihrem Skateboard dunk Leichtathletik sein, erst spƤter angepasst klassische Schuhe oder Stiefel vielleicht kƶnnen, welche Art weitermachen recht sein das Top-Event Skateboarding. In Tim Deborah Ć¼ber die der Nike SB Engagement, ist die Stadt nicht gehen, um die wunderbare Art, die zahlreichen Spiel qualifizieren. Nike preiswerte beilƤufige Sprach-Features und zusƤtzlich nƤher Folk reagiert ganz geben ein, um das Brot zu vermeiden, jeder unter den EM beschleunigt Position unterstĆ¼tzen Sie installieren den ganzen Weg bis in den Horizont zu sehen, die mit dem tƤglichen Leben gefĆ¼llt wird, bedeutet der stoĆdƤmpfenden Leistung. Der Weg der Skateboard-Schuhe oder vielleicht Schuh, hat denn das eine wirklich wundervolle FlexibilitƤt, Entwicklungshilfe, Sicherheit zu nutzen. GruĆ an nike air max Steckdose formal Website Vereinigten Says, billig nike air max Schuhe fĆ¼r MƤnner, MƤdchen, Verkauf von 40% -70% der ultra billige Discount cost.The Lyons Kopf im Fluss jedoch gehen, fliegt der Yan mit den Fersen nach schlieĆen Tod, hƤlt Luft maximal 87 ein Licht prompt und zusƤtzlich fangen raubt Vordergrund die Nudeln fĆ¼hrt der Weg, in sich die Halle ist sich bewusst sein, das Herrenhaus Erwachsenen nach UnterstĆ¼tzung Halle empfƤngt den Gast Ziel und auch wirklich elegant gesetzt, Paket steigen 4 Sohn Unterarme Dense groĆen Leuchter, leuchten Ć¼ber die ganze Halle eins ist hochwertig. Doch in den Sitz der Gastgeber ruhen, aber eine mittlere Alter, die in grĆ¼nem Damast Kleidung, ein Gesicht kalt Su von kosmetischen Reflexion, die nike air max 95, die die Villa ist wirklich auch ein Gesicht wirklich Huang und zusƤtzlich mƶglicherweise von Farb gekleidet ist, Rest neben, eigentlich das Ambiente nicht wagen, schwer atmen ein Schluck seit gut Fluss ist eine lange Strecke plƶtzlich die HƤnde sind wirklich ein Zheng, die Handschellen spaltet und Scatter 1. Es scheint zu sein, wirklich cool. Es Namen boot, aber manchmal werden Sie den Cisco Kind in den traditionellen Schuhe entdecken? Und es ist ein Jogging-Schuhe oder Stiefel fĆ¼r Damen, die es von mehreren imitieren Produkt Publikationen hergestellt. Es gehƶrt in breite Palette von Nike Shox R4 Top QualitƤt und Air Antrieb 1 Supreme. Ist es nicht neue Politik, um die Hƶhe der Mittel frei von Damen-Geldbƶrse zu greifen. Im Gegensatz zu einigen anderen Boot Gegensatz es zum FlieĆen ausgelegt, kƶnnte man auf Sportbekleidung oder vielleicht Job KleidungsstĆ¼cke platzieren. Sie kƶnnen mƶglicherweise auch mit
Re: [PATCH v3 3/7] t/t2012-checkout-last: test checkout - after a rebase
Am 6/19/2013 10:04, schrieb Ramkumar Ramachandra: +test_expect_failure 'checkout - works after a rebase -i A B' ' + git branch foodle master~1 + git checkout master + git checkout other + git rebase master foodle git rebase -i master foodle + git checkout - + test z$(git symbolic-ref HEAD) = zrefs/heads/master +' + test_done -- Hannes -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 3/7] t/t2012-checkout-last: test checkout - after a rebase
Johannes Sixt wrote: Am 6/19/2013 10:04, schrieb Ramkumar Ramachandra: +test_expect_failure 'checkout - works after a rebase -i A B' ' + git branch foodle master~1 + git checkout master + git checkout other + git rebase master foodle git rebase -i master foodle Good eyes. Thanks. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/6] t/t5528-push-default: test pushdefault workflows
Introduce test_pushdefault_workflows(), and test that all push.default modes work with central and triangular workflows as expected. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- t/t5528-push-default.sh | 36 1 file changed, 36 insertions(+) diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index b599186..eabc09d 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -39,6 +39,26 @@ test_push_failure () { test_cmp expect actual } +# $1 = success or failure +# $2 = push.default value +# $3 = branch to check for actual output (master or foo) +# $4 = [optional] switch to triangular workflow +test_pushdefault_workflow () { + workflow=central + pushdefault=parent1 + if test -n ${4-}; then + workflow=triangular + pushdefault=parent2 + fi +test_expect_success push.default = $2 $1 in $workflow workflows + test_config branch.master.remote parent1 + test_config branch.master.merge refs/heads/foo + test_config remote.pushdefault $pushdefault + test_commit commit-for-$2${4+-triangular} + test_push_$1 $2 $3 ${4+repo2} + +} + test_expect_success 'upstream pushes to configured upstream' ' git checkout master test_config branch.master.remote parent1 @@ -115,4 +135,20 @@ test_expect_success 'push to existing branch, upstream configured with different test_cmp expect-other-name actual-other-name ' +## test_pushdefault_workflow() arguments: +# $1 = success or failure +# $2 = push.default value +# $3 = branch to check for actual output (master or foo) +# $4 = [optional] switch to triangular workflow + +test_pushdefault_workflow success current master # breaks push/pull symmetry +test_pushdefault_workflow success upstream foo# preserves push/pull symmetry +test_pushdefault_workflow failure simple master # errors out on asymmetry +test_pushdefault_workflow success matching master # always works + +test_pushdefault_workflow success current master triangular # always works +test_pushdefault_workflow failure upstream foo triangular# always errors out +test_pushdefault_workflow success simple master triangular # works like current +test_pushdefault_workflow success matching master triangular # always works + test_done -- 1.8.3.1.454.g30263f3.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/6] t/t5528-push-default: generalize test_push_*
The setup creates two bare repositories: repo1 and repo2, but test_push_commit() hard-codes checking in repo1 for the actual output. Generalize it and its caller, test_push_success(), to optionally accept a third argument to specify the name of the repository to check for actual output. We will use this in the next patch. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- t/t5528-push-default.sh | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index e54dd02..b599186 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -15,17 +15,19 @@ test_expect_success 'setup bare remotes' ' # $1 = local revision # $2 = remote revision (tested to be equal to the local one) +# $3 = [optional] repo to check for actual output (repo1 by default) check_pushed_commit () { git log -1 --format='%h %s' $1 expect - git --git-dir=repo1 log -1 --format='%h %s' $2 actual + git --git-dir=${3:-repo1} log -1 --format='%h %s' $2 actual test_cmp expect actual } # $1 = push.default value # $2 = expected target branch for the push +# $3 = [optional] repo to check for actual output (repo1 by default) test_push_success () { git -c push.default=$1 push - check_pushed_commit HEAD $2 + check_pushed_commit HEAD $2 $3 } # $1 = push.default value -- 1.8.3.1.454.g30263f3.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/6] push.default in the triangular world
[2/6] documents existing push.default modes properly, but doesn't touch `simple`. It incorporates feedback from Junio, Philip Oakley, Matthieu Moy. [3/6] gives `simple` an exciting new meaning. I think it's an absolutely fabulous default! It's aimed at triangular people who occassionally need to do central stuff. [6/6] adds some new tests to illustrate how all these push.default modes work in central and triangular workflows. Thanks. Ramkumar Ramachandra (6): t/t5528-push-default: remove redundant test_config lines config doc: rewrite push.default section push: change `simple` to accommodate triangular workflows push: remove dead code in setup_push_upstream() t/t5528-push-default: generalize test_push_* t/t5528-push-default: test pushdefault workflows Documentation/config.txt | 62 ++-- builtin/push.c | 27 + t/t5528-push-default.sh | 46 +++ 3 files changed, 97 insertions(+), 38 deletions(-) -- 1.8.3.1.454.g30263f3.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/6] push: change `simple` to accommodate triangular workflows
When remote.pushdefault or branch.name.pushremote is set (a triangular workflow feature), master@{u} != origin, and push.default is set to `upstream` or `simple`: $ git push fatal: You are pushing to remote 'origin', which is not the upstream of your current branch 'master', without telling me what to push to update which remote branch. Unfortunately, in the case of `upstream`, the very name indicates that it is only suitable for use in central workflows; let us not even attempt to give it a new meaning in triangular workflows, and error out as usual. However, the `simple` does not have this problem: it is poised to be the default for Git 2.0, and we would definitely like it to do something sensible in triangular workflows. Decouple `simple` from `upstream` completely, and change it to mean `current` with a safety feature: a `push` and `pull` should not be asymmetrical in the special case of central workflows. Reported-by: Leandro Lucarella leandro.lucare...@sociomantic.com Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- Documentation/config.txt | 10 ++ builtin/push.c | 21 - t/t5528-push-default.sh | 2 +- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 9f04f74..81628e8 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1850,10 +1850,12 @@ push.default:: symmetrical to `pull` in central workflows, and cannot be used in non-central workflows. -* `simple` - like `upstream`, but refuses to push if the upstream - branch's name is different from the local one. This is the safest - option and is well-suited for beginners. It will become the default - in Git 2.0. +* `simple` - a safer version of `current`; push the current branch to + update a branch with the same name on the receiving end, with a + safety feature: in central workflows, error out if + branch.$branch.merge is set and not equal to $branch, to make sure + that a `push` and `push` are never asymmetrical. It will become the + default in Git 2.0. * `matching` - push all branches having the same name on both ends (essentially ignoring all newly created local branches). diff --git a/builtin/push.c b/builtin/push.c index 2d84d10..d8d27d9 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -120,6 +120,25 @@ static const char message_detached_head_die[] = \n git push %s HEAD:name-of-remote-branch\n); +static void setup_push_simple(struct remote *remote) +{ + struct branch *branch = branch_get(NULL); + if (!branch) + die(_(message_detached_head_die), remote-name); + if (!branch-merge_nr || !branch-merge || !branch-remote_name) + /* No upstream configured */ + goto end; + if (branch-merge_nr != 1) + die(_(The current branch %s has multiple upstream branches, + refusing to push.), branch-name); + if (!strcmp(branch-remote_name, remote-name) + strcmp(branch-refname, branch-merge[0]-src)) + /* Central workflow safety feature */ + die_push_simple(branch, remote); +end: + add_refspec(branch-name); +} + static void setup_push_upstream(struct remote *remote, int simple) { struct strbuf refspec = STRBUF_INIT; @@ -188,7 +207,7 @@ static void setup_default_push_refspecs(struct remote *remote) break; case PUSH_DEFAULT_SIMPLE: - setup_push_upstream(remote, 1); + setup_push_simple(remote); break; case PUSH_DEFAULT_UPSTREAM: diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index 69ce6bf..e54dd02 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -85,7 +85,7 @@ test_expect_success 'push from/to new branch with current creates remote branch' test_expect_success 'push to existing branch, with no upstream configured' ' test_config branch.master.remote repo1 git checkout master - test_push_failure simple + test_push_success simple master test_push_failure upstream ' -- 1.8.3.1.454.g30263f3.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/6] push: remove dead code in setup_push_upstream()
Now that simple has been decoupled from upstream in setup_push_simple(), remove the dead code in setup_push_upstream(). Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- builtin/push.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/builtin/push.c b/builtin/push.c index d8d27d9..783bacf 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -139,7 +139,7 @@ end: add_refspec(branch-name); } -static void setup_push_upstream(struct remote *remote, int simple) +static void setup_push_upstream(struct remote *remote) { struct strbuf refspec = STRBUF_INIT; struct branch *branch = branch_get(NULL); @@ -161,8 +161,6 @@ static void setup_push_upstream(struct remote *remote, int simple) your current branch '%s', without telling me what to push\n to update which remote branch.), remote-name, branch-name); - if (simple strcmp(branch-refname, branch-merge[0]-src)) - die_push_simple(branch, remote); strbuf_addf(refspec, %s:%s, branch-name, branch-merge[0]-src); add_refspec(refspec.buf); @@ -211,7 +209,7 @@ static void setup_default_push_refspecs(struct remote *remote) break; case PUSH_DEFAULT_UPSTREAM: - setup_push_upstream(remote, 0); + setup_push_upstream(remote); break; case PUSH_DEFAULT_CURRENT: -- 1.8.3.1.454.g30263f3.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/6] config doc: rewrite push.default section
4d3592 (Merge branch 'rr/triangle', 2013-04-07) introduced support for triangular workflows in Git, but the push.default values still assume central workflows. Rewrite the descriptions of `nothing`, `current`, `upstream` and `matching` for greater clarity, and explicitly explaining how they behave in triangular workflows. Leave `simple` as it is for the moment, as we plan to change its meaning to accommodate triangular workflows in a later patch. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- Documentation/config.txt | 56 ++-- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 7fd4035..9f04f74 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1826,39 +1826,43 @@ pull.twohead:: The default merge strategy to use when pulling a single branch. push.default:: - Defines the action `git push` should take if no refspec is given - on the command line, no refspec is configured in the remote, and - no refspec is implied by any of the options given on the command - line. Possible values are: + Defines the action `git push` should take if no refspec is + explicitly given. Different values are well-suited for + specific workflows; for instance, in a purely central workflow + (i.e. the fetch source is equal to the push destination), + `upstream` is probably what you want. Possible values are: + -- -* `nothing` - do not push anything. -* `matching` - push all branches having the same name in both ends. - This is for those who prepare all the branches into a publishable - shape and then push them out with a single command. It is not - appropriate for pushing into a repository shared by multiple users, - since locally stalled branches will attempt a non-fast forward push - if other users updated the branch. - + - This is currently the default, but Git 2.0 will change the default - to `simple`. -* `upstream` - push the current branch to its upstream branch - (`tracking` is a deprecated synonym for this). - With this, `git push` will update the same remote ref as the one which - is merged by `git pull`, making `push` and `pull` symmetrical. - See branch.name.merge for how to configure the upstream branch. +* `nothing` - do not push anything (error out) unless a refspec is + explicitly given. Very safe, but not very convenient. + +* `current` - push the current branch to update a branch with the same + name on the receiving end. Works in both central and non-central + workflows. Equivalent to pushing the refspec $branch ($branch is + the name of the current branch). + +* `upstream` - push the current branch to a branch with the name + branch.$branch.merge on the receiving end, and error out if the push + destination is not the same as branch.$branch.remote. The name + upstream refers to @{u[pstream]} in linkgit:gitrevisions[7], + which makes sense only if both branch.$branch.remote and + branch.$branch.merge are set. It makes sure that a `push` is + symmetrical to `pull` in central workflows, and cannot be used in + non-central workflows. + * `simple` - like `upstream`, but refuses to push if the upstream branch's name is different from the local one. This is the safest option and is well-suited for beginners. It will become the default in Git 2.0. -* `current` - push the current branch to a branch of the same name. + +* `matching` - push all branches having the same name on both ends + (essentially ignoring all newly created local branches). + Well-suited for those who want to batch-update a specific set of + branches they consistently work on. Use with caution, especially + when pushing with '--force'. Equivalent to pushing the refspec :. + This is currently the default, but Git 2.0 will change the default + to `simple`. -- -+ -The `simple`, `current` and `upstream` modes are for those who want to -push out a single branch after finishing work, even when the other -branches are not yet ready to be pushed out. If you are working with -other people to push into the same shared repository, you would want -to use one of these. rebase.stat:: Whether to show a diffstat of what changed upstream since the last -- 1.8.3.1.454.g30263f3.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/6] t/t5528-push-default: remove redundant test_config lines
The line test_config push.default upstream appears unnecessarily in two tests, as the final test_push_failure sets push.default before pushing anyway. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- t/t5528-push-default.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index 4736da8..69ce6bf 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -48,7 +48,6 @@ test_expect_success 'upstream pushes to configured upstream' ' test_expect_success 'upstream does not push on unconfigured remote' ' git checkout master test_unconfig branch.master.remote - test_config push.default upstream test_commit three test_push_failure upstream ' @@ -57,7 +56,6 @@ test_expect_success 'upstream does not push on unconfigured branch' ' git checkout master test_config branch.master.remote parent1 test_unconfig branch.master.merge - test_config push.default upstream test_commit four test_push_failure upstream ' -- 1.8.3.1.454.g30263f3.dirty -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2] send-email: allow use of basic email list in --cc --to and --bcc
From: Jorge Juan Garcia Garcia jorge-juan.garcia-gar...@ensimag.imag.fr Make it so that we can use a list of email in flags instead of having to use one flag per email address. The use-case is to copy-paste a list of addresses from an email. This change makes it so that we no longer need to cut the list. The format of email list handled is pretty basic for now: $ git send-email --to='Foo f...@example.com, b...@example.com' We thought it would be nice to have a first-step version which works before handling more complex ones such as names with commas: $ git send-email --to='Foo, Bar foo...@example.com' This artificial limitation is imposed by 79ee555b (Check and document the options to prevent mistakes, 2006-06-21). Signed-off-by: Mathieu Lienard--Mayor mathieu.lienard--ma...@ensimag.imag.fr Signed-off-by: Jorge Juan Garcia Garcia jorge-juan.garcia-gar...@ensimag.imag.fr Signed-off-by: Matthieu Moy matthieu@grenoble-inp.fr --- Changes since v1: - more detailed commit message, explaining the most common use-case, and referring to the commit which introduced the comma limitation - use of map in the function, to match sanitize_address_list - did not change the two regexp into one, because it's faster with two Documentation/git-send-email.txt | 21 +++-- git-send-email.perl | 36 ++-- t/t9001-send-email.sh| 37 - 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt index 40a9a9a..e3444cf 100644 --- a/Documentation/git-send-email.txt +++ b/Documentation/git-send-email.txt @@ -50,16 +50,22 @@ Composing 'sendemail.multiedit'. --bcc=address:: +--bcc=[address,...]:: Specify a Bcc: value for each email. Default is the value of 'sendemail.bcc'. -+ -The --bcc option must be repeated for each user you want on the bcc list. + The format supported for email list is the following: + Foo f...@example.com, b...@example.com. + Please notice that the email list does not handle commas in + email names such as Foo, Bar foo...@example.com. --cc=address:: +--cc=[address,...]:: Specify a starting Cc: value for each email. Default is the value of 'sendemail.cc'. -+ -The --cc option must be repeated for each user you want on the cc list. + The format supported for email list is the following: + Foo f...@example.com, b...@example.com. + Please notice that the email list does not handle commas in + email names such as Foo, Bar foo...@example.com. --compose:: Invoke a text editor (see GIT_EDITOR in linkgit:git-var[1]) @@ -111,12 +117,15 @@ is not set, this will be prompted for. is not set, this will be prompted for. --to=address:: +--to=[address,...]:: Specify the primary recipient of the emails generated. Generally, this will be the upstream maintainer of the project involved. Default is the value of the 'sendemail.to' configuration value; if that is unspecified, and --to-cmd is not specified, this will be prompted for. -+ -The --to option must be repeated for each user you want on the to list. + The format supported for email list is the following: + Foo f...@example.com, b...@example.com. + Please notice that the email list does not handle commas in + email names such as Foo, Bar foo...@example.com. --8bit-encoding=encoding:: When encountering a non-ASCII message or subject that does not diff --git a/git-send-email.perl b/git-send-email.perl index 671762b..03f3876 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -426,20 +426,6 @@ my ($repoauthor, $repocommitter); ($repoauthor) = Git::ident_person(@repo, 'author'); ($repocommitter) = Git::ident_person(@repo, 'committer'); -# Verify the user input - -foreach my $entry (@initial_to) { - die Comma in --to entry: $entry'\n unless $entry !~ m/,/; -} - -foreach my $entry (@initial_cc) { - die Comma in --cc entry: $entry'\n unless $entry !~ m/,/; -} - -foreach my $entry (@bcclist) { - die Comma in --bcclist entry: $entry'\n unless $entry !~ m/,/; -} - sub parse_address_line { if ($have_mail_address) { return map { $_-format } Mail::Address-parse($_[0]); @@ -1079,6 +1065,25 @@ sub smtp_auth_maybe { return $auth; } +sub split_emails { +my ($emails) = @_; +my @split_list; +if ($emails =~ /,/) { + @split_list = split(/,/, $emails); +} else { + @split_list = $emails; +} +# Removal of unwanted spaces +for (my $j = 0; $j = $#split_list; $j++) { + $split_list[$j] =~ s/^\s+//; + $split_list[$j] =~ s/\s+$//; +} +return @split_list; +} + +sub split_emails_list { + return (map { split_emails($_) } @_); +} # Returns 1 if the message was sent, and 0 otherwise. #
Re: [Request] Git reset should be able to ignore file permissions
Alexander Nestorov alexander...@gmail.com writes: Ok, this is how it looks. If everything is ok, I'm sending it to the ML Please, read Documentation/SubmittingPatches (you lack a sign-off and if you think the patch is ready, you should Cc Junio). Also, it's better to have the commit headers directly as mail headers (git send-email is your friend). +Reset only files who's content changed (instead of stat information):: That's still not 100% accurate. Actual mode changes would trigger a rewrite of the file. Perhaps stg like Reset only files which actually changed (not those with only stat information change):: (Sorry for nitpicking so much) -- Matthieu Moy http://www-verimag.imag.fr/~moy/ -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2] send-email: allow use of basic email list in --cc --to and --bcc
jorge-juan.garcia-gar...@ensimag.imag.fr writes: Changes since v1: [...] - did not change the two regexp into one, because it's faster with two (I find it strange to describe non-change in a list of changes) I don't think speed is an argument here: it's a one-time operation and will be instantaneous for the user in any case. +sub split_emails { +my ($emails) = @_; +my @split_list; +if ($emails =~ /,/) { + @split_list = split(/,/, $emails); +} else { + @split_list = $emails; +} Do you need this if? Wouldn't split do the right thing if $emails does not contain comma? +# Removal of unwanted spaces +for (my $j = 0; $j = $#split_list; $j++) { Sounds very un-perl-ish. Something like this maybe? foreach $email (@emails) { $email =~ s/^\s+|\s+$//; } +return @split_list; +} This is indented with tab/spaces mix. Please, use tabs only in Git's source. -- Matthieu Moy http://www-verimag.imag.fr/~moy/ -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] Documentation: Update 'linux-2.6.git' - 'linux.git'
On Tue, Jun 18, 2013 at 10:05:50PM -0700, David Aguilar wrote: On Tue, Jun 18, 2013 at 6:55 PM, W. Trevor King wk...@tremily.us wrote: -$ git clone --bare -l -s /pub/scm/.../torvalds/linux-2.6.git \ +$ git clone --bare -l -s /pub/scm/.../torvalds/linux.git \ /pub/scm/.../me/subsys-2.6.git Perhaps subsys.git instead of subsys-2.6.git too? Good point. `git grep -- -2.6.git` also turns up a few references to git://linux-nfs.org/pub/nfs-2.6.git, but I can't figure out where that has gone. It looks like the NFS folks only have personal repositories anymore [1]. Cheers, Trevor [1]: http://git.linux-nfs.org/ -- This email may be signed or encrypted with GnuPG (http://www.gnupg.org). For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy signature.asc Description: OpenPGP digital signature
accessing oldest reflog entry with ref@{N}?
Hi, after a couple of months of inactivity I recently updated my git clone from the main repo, and later ran 'git gc', which, of course, dutifully pruned the old reflog entries, leaving my reflogs quite shallow: $ git reflog master 0dbd8125 master@{0}: merge origin/master: Fast-forward f3828dc0 Then later I had to access the previous state, which I usually do with master@{1}, but not this time: $ git log --oneline -1 master@{1} fatal: Log for 'master' only has 1 entries. Annoyed, I just copy-pasted the sha and got the job done. However, I wonder why it didn't worked. 'git reflog' didn't print master@{1} or any message for the oldest entry, but I can live without that. The sha is undoubtedly there, however, so git should know where master@{1} points and should Just Work, shouldn't it? Thanks, GƔbor -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
On 2013-06-19 01:56, Ramkumar Ramachandra wrote: From gitglossary(7): ref A 40-byte hex representation of a SHA-1 or a name that denotes a particular object. They may be stored in a file under $GIT_DIR/refs/ directory, or in the $GIT_DIR/packed-refs file. Do master~3 and :/foomery qualify as refs? Yes; they are names that denote a particular object. Look at the other forms in gitrevisions(7); master:quuxery, master^{tree} are notable exceptions. gitrevisions(7) says that master:quuxery is a ref pointing to a blob or tree, so it is not a committish. However, if quuxery is a submodule, I would expect master:quuxery to point to a commit object and thus be a committish. So perhaps the rev:path description in gitrevisions(7) should be updated to accommodate submodules. When quuxery is a submodule, master:quuxery refers to a commit object that does not exist in the parent repository. I don't know what we gain by documenting a comittish you can't even `show`. Fair point. -Richard -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/3] Fix a race condition when reading loose refs
On Wed, Jun 19, 2013 at 08:36:25AM +0200, Michael Haggerty wrote: I took Peff's suggestion to use gotos rather than an infinite loop in the last patch, which means that there is no need for the old patch 03/04. Thanks, this version looks good to me. I'm sure the Pascal programmers of the world collectively sighed in disgust at a code review requesting a for loop turn into a goto, but I think it is more readable than the first version. :) -Peff -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
On 2013-06-19 11:31, Richard Hansen wrote: On 2013-06-19 01:56, Ramkumar Ramachandra wrote: From gitglossary(7): ref A 40-byte hex representation of a SHA-1 or a name that denotes a particular object. They may be stored in a file under $GIT_DIR/refs/ directory, or in the $GIT_DIR/packed-refs file. Do master~3 and :/foomery qualify as refs? Yes; they are names that denote a particular object. Hmm... Maybe not. There is no definition of name in gitglossary(7), but there is object name, and that says: object name The unique identifier of an object. The hash of the object's contents using the Secure Hash Algorithm 1 and usually represented by the 40 character hexadecimal encoding of the hash of the object. That definition excludes master~3 and :/foomery. So perhaps we need a clearer definition of ref, or add a separate definition of name that is distinct from object name, or change the definition of object name to be more general (and perhaps define object ID to take the current definition of object name?). In sha1_name.c, master~3 and :/foomery are considered to be names. I think it'd be a good idea if gitglossary(7) matched the code, because that's the vocabulary Git developers and power users will use. Unfortunately, in my mind name has a connotation that doesn't quite match what sha1_name.c considers to be a name (I think of name as an arbitrary, more-or-less semanticless label attached to something for the purpose of convenient identification; the stuff in gitrevisions(7) are more like operators on a name). Maybe object specifier (objspec for short) could be used to refer to all the ways one could specify an object? Similarly, commit specifier/commitspec, tree specifier/treespec, etc. A treeish would then be defined as a treespec or something that can be dereferenced to a treespec. BTW, I'm not a huge fan of the current definition of ref in gitglossary(7) because to me a ref is ONLY something in .git/refs (or HEAD, FETCH_HEAD, etc.) -- NOT a SHA1. But I used ref in the definition of committish because that's how the definition of tree-ish was worded. It's also unfortunate that gitrevisions(7) isn't just about specifying revisions -- it's about specifying any object. Anyway, although my patches aren't perfect, I think they improve the current situation. If there are no objections I would like to see them committed. Thanks, Richard -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Request] Git reset should be able to ignore file permissions
On 19 June 2013 01:00, Alexander Nestorov alexander...@gmail.com wrote: Ok, this is how it looks. If everything is ok, I'm sending it to the ML From 262bdfb5cc84fec7c9b74dc92bb604f9d168ef9a Mon Sep 17 00:00:00 2001 From: Alexander Nestorov alexander...@gmail.com Date: Wed, 19 Jun 2013 09:55:42 +0200 Subject: [PATCH] Add example for reseting based on content changes instead of stat changes --- Documentation/git-reset.txt | 12 1 file changed, 12 insertions(+) diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt index a404b47..da639e9 100644 --- a/Documentation/git-reset.txt +++ b/Documentation/git-reset.txt @@ -289,6 +289,18 @@ $ git reset --keep start3 3 But you can use reset --keep to remove the unwanted commit after you switched to branch2. +Reset only files who's content changed (instead of stat information):: You should use whose here instead of who's. ++ + +$ git update-index --refresh 1 +$ git reset --hard 2 + ++ +1 Make Git realize which files actually changed instead of +checking out all files whether their content changed or only +their mtime changed. +2 Now git reset --hard will checkout only the files that +actually changed. DISCUSSION -- -- 1.8.1.msysgit.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 6/7] rebase: write better reflog messages
Johannes Sixt j.s...@viscovery.net writes: Am 6/18/2013 20:55, schrieb Ramkumar Ramachandra: Now that the checkout invoked internally from rebase knows to honor GIT_REFLOG_ACTION, we can start to use it to write a better reflog message when rebase anotherbranch, rebase --onto branch, etc. internally checks out the new fork point. We will write: rebase: checkout master instead of the old rebase diff --git a/git-rebase--am.sh b/git-rebase--am.sh index 34e3102..69fae7a 100644 --- a/git-rebase--am.sh +++ b/git-rebase--am.sh @@ -5,11 +5,13 @@ case $action in continue) +GIT_REFLOG_ACTION=$base_reflog_action I haven't followed the topic closely, but I wonder why there are so many explicit assignments to GIT_REFLOG_ACTION. Is calling set_reflog_action (defined in git-sh-setup) the wrong thing to do? Excellent question, and I think this illustrates why the recent reroll that uses an approach to use base_reflog_action is not complete and needs further work (to put it mildly). set_reflog_action is designed to be used once at the very top of a program, like this in git am, for example: set_reflog_action am The helper function sets the given string to GIT_REFLOG_ACTION only when GIT_REFLOG_ACTION is not yet set. Thanks to this, git am, when run as the top-level program, will use am in GIT_REFLOG_ACTION and the reflog entries made by whatever it does will say am did this. Because of the conditional assignment, when git am is run as a subprogram (i.e. an implementation detail) of git rebase, the call to the helper function at the beginning will *not* have any effect. So git rebase can do this: set_reflog_action rebase ... do its own preparation, like checking out onto commit ... decide to do format-patch to am pipeline git format-patch --stdout mbox git am mbox and the reflog entries made inside git am invocation will say rebase, not am. The approach to introduce base_reflog_action may be valid, but if we were to go that route, set_reflog_action needs to learn the new convention. Perhaps by doing something like this: 1. set_reflog_action to set GIT_REFLOG_NAME and GIT_REFLOG_ACTION; Program names like am, rebase will be set to this value. 2. If the program does not want to say anything more than its program name in the reflog, it does not have to do anything. GIT_REFLOG_ACTION that is set upfront (or inherited from the calling program) will be written in the reflog. 3. If the program wants to say more than just its name, it needs to arrange GIT_REFLOG_ACTION not to be clobbered. It can do so in various ways: a) A one-shot invocation of any program that writes to reflog can do: GIT_REFLOG_ACTION=$GIT_REFLOG_NAME: custom message \ git cmd An important thing is that GIT_REFLOG_ACTION is left as the original, i.e. am or rebase, so that calls to programs that write reflog using the default (i.e. program name only) will not be affected. b) Or it can temporarily change it and revert it back (necessary to use shell function like output that cannot use the above single shot export technique): GIT_REFLOG_ACTION=$GIT_REFLOG_NAME: custom message output git cmd GIT_REFLOG_ACTION=$GIT_REFLOG_NAME But after writing it down this way, I realize that introduction of base_reflog_action (or GIT_REFLOG_NAME which is a moral equivalent) is not helping us at all. As long as calls to git command in the second category exists in these scripts, GIT_REFLOG_ACTION *must* be kept pristine after set_reflog_action sets it, so we can get rid of this new variable, and rewrite 3.a and 3.b like so: 3-a) GIT_REFLOG_ACTION=$GIT_REFLOG_ACTION: custom message \ git cmd 3-b) SAVED=$GIT_REFLOG_ACTION GIT_REFLOG_ACTION=$GIT_REFLOG_ACTION: custom message output git cmd GIT_REFLOG_ACTION=$SAVED or ( GIT_REFLOG_ACTION=$GIT_REFLOG_ACTION: custom message output git cmd ) That essentially boils down to the very original suggestion I made before Ram introduced the base_reflog_action. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] Documentation: Update 'linux-2.6.git' - 'linux.git'
W. Trevor King wk...@tremily.us writes: diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index a0727d7..8e5260f 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -274,7 +274,7 @@ $ git clone --bare -l /home/proj/.git /pub/scm/proj.git * Create a repository on the kernel.org machine that borrows from Linus: + -$ git clone --bare -l -s /pub/scm/.../torvalds/linux-2.6.git \ +$ git clone --bare -l -s /pub/scm/.../torvalds/linux.git \ /pub/scm/.../me/subsys-2.6.git Aside from s|subsys-2.6|subsys| David already mentioned, I think it is a lot saner to remove this particular example. Nobody runs shell on k.org machines these days, and local borrowing -l -s is already shown in another example. Also you seem to have missed another linux-2.6 my2.6 clone in the first example. Will not apply in this form; expecting a reroll. Thanks. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] user-manual: Update download size for Git and the kernel
Thanks, will queue. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] glossary: add 'treeish' as a synonym for 'tree-ish'
Richard Hansen rhan...@bbn.com writes: The documentation contains a mix of the two spellings, and including both makes it possible for users to search the glossary with their spelling of choice. Is it an option to instead find dashless form in our documentation and turn all of them into tree-ish form with a dash? I personally find it cleaner that way. Signed-off-by: Richard Hansen rhan...@bbn.com --- Documentation/glossary-content.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index db2a74d..01365d9 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -486,7 +486,7 @@ should not be combined with other pathspec. with refs to the associated blob and/or tree objects. A def_tree,tree is equivalent to a def_directory,directory. -[[def_tree-ish]]tree-ish:: +[[def_tree-ish]]tree-ish (also treeish):: A def_ref,ref pointing to either a def_commit_object,commit object, a def_tree_object,tree object, or a def_tag_object,tag object pointing to a tag or commit or tree object. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
Richard Hansen rhan...@bbn.com writes: Signed-off-by: Richard Hansen rhan...@bbn.com --- Documentation/glossary-content.txt | 11 +++ 1 file changed, 11 insertions(+) diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index 01365d9..a3cc003 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -82,6 +82,17 @@ to point at the new commit. to the top def_directory,directory of the stored revision. +[[def_committish]]committish (also commit-ish):: + A def_ref,ref pointing to an def_object,object that + can be recursively dereferenced to a + def_commit_object,commit object. + The following are all committishes: + a ref pointing to a commit object, + a ref pointing to a def_tag_object,tag object that points + to a commit object, + a ref pointing to a tag object that points to a tag object + that points to a commit object, etc. + object-type-ish does not have anything to do with a ref. Even when an object is dangling in your object store without being reachable from any of your refs, it keeps its own ish-ness. ish-ness is a property of the object itself. * A commit object has a single top-level tree, and when a command wants a tree object, you can often pass it a commit (historically some commands were more strict and refused to work on a commit when they wanted a tree). In other words, a commit can be used in place for a tree. A commit object is a tree-ish. * A tag object, when it points (recursively) at a commit object, can often be used in place for a commit object. Such a tag object is a commit-ish. * A tag object, when it points (recursively) at a tree object, can often be used in place for a tree object. Such a tag object is a tree-ish. Note that such a tag object cannot be a commit-ish. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/3] Fix a race condition when reading loose refs
Jeff King p...@peff.net writes: On Wed, Jun 19, 2013 at 08:36:25AM +0200, Michael Haggerty wrote: I took Peff's suggestion to use gotos rather than an infinite loop in the last patch, which means that there is no need for the old patch 03/04. Thanks, this version looks good to me. I'm sure the Pascal programmers of the world collectively sighed in disgust at a code review requesting a for loop turn into a goto, but I think it is more readable than the first version. :) -Peff Thanks, both. Essentially the first two are the same from the previous round, and the third one gives us oops, unexpected state---let's retry in a more straight-forward way. Looks very sensible; will queue. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 6/7] rebase: write better reflog messages
Junio C Hamano gits...@pobox.com writes: Excellent question, and I think this illustrates why the recent reroll that uses an approach to use base_reflog_action is not complete and needs further work (to put it mildly). ... That essentially boils down to the very original suggestion I made before Ram introduced the base_reflog_action. So how about doing something like this? Incidentally, I noticed that GIT_LITERAL_PATHSPECS:: heading in the enumeration of environment variables is marked-up differently from others, which is a low-hanging fruit somebody may want to fix. Documentation/git-sh-setup.txt | 8 +--- Documentation/git.txt | 10 ++ git-sh-setup.sh| 34 ++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/Documentation/git-sh-setup.txt b/Documentation/git-sh-setup.txt index 5d709d0..4f67c4c 100644 --- a/Documentation/git-sh-setup.txt +++ b/Documentation/git-sh-setup.txt @@ -41,9 +41,11 @@ usage:: die with the usage message. set_reflog_action:: - set the message that will be recorded to describe the - end-user action in the reflog, when the script updates a - ref. + Set GIT_REFLOG_ACTION environment to a given string (typically + the name of the program) unless it is already set. Whenever + the script runs a `git` command that updates refs, a reflog + entry is created using the value of this string to leave the + record of what command updated the ref. git_editor:: runs an editor of user's choice (GIT_EDITOR, core.editor, VISUAL or diff --git a/Documentation/git.txt b/Documentation/git.txt index 2e23cbb..e2bdcc9 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -846,6 +846,16 @@ GIT_LITERAL_PATHSPECS:: literal paths to Git (e.g., paths previously given to you by `git ls-tree`, `--raw` diff output, etc). +'GIT_REFLOG_ACTION':: + When a ref is updated, reflog entries are created to keep + track of the reason why the ref was updated (which is + typically the name of the high-level command that updated + the ref), in addition to the old and new values of the ref. + A scripted Porcelain command can use set_reflog_action + helper function in `git-sh-setup` to set its name to this + variable when it is invoked as the top level command by the + end user, to be recorded in the body of the reflog. + Discussion[[Discussion]] diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 2f78359..e5379bc 100644 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -103,6 +103,40 @@ $LONG_USAGE esac fi +# Set the name of the end-user facing command in the reflog when the +# script may update refs. When GIT_REFLOG_ACTION is already set, this +# will not overwrite it, so that a scripted Porcelain (e.g. git +# rebase) can set it to its own name (e.g. rebase) and then call +# another scripted Porcelain (e.g. git am) and a call to this +# function in the latter will keep the name of the end-user facing +# program (e.g. rebase) in GIT_REFLOG_ACTION, ensuring whatever it +# does will be record as actions done as part of the end-user facing +# operation (e.g. rebase). +# +# NOTE NOTE NOTE: consequently, after assigning a specific message to +# GIT_REFLOG_ACTION when calling a git command to record a custom +# reflog message, do not leave that custom value in GIT_REFLOG_ACTION, +# after you are done. Other callers of git commands that rely on +# writing the default program name in reflog expect the variable to +# contain the value set by this function. +# +# To use a custom reflog message, do either one of these three: +# +# (a) use a single-shot export form: +# GIT_REFLOG_ACTION=$GIT_REFLOG_ACTION: preparing frotz \ +# git command-that-updates-a-ref +# +# (b) save the original away and restore: +# SAVED_ACTION=$GIT_REFLOG_ACTION +# GIT_REFLOG_ACTION=$GIT_REFLOG_ACTION: preparing frotz +# git command-that-updates-a-ref +# GIT_REFLOG_ACITON=$SAVED_ACTION +# +# (c) assign the variable in a subshell: +# ( +# GIT_REFLOG_ACTION=$GIT_REFLOG_ACTION: preparing frotz +# git command-that-updates-a-ref +# ) set_reflog_action() { if [ -z ${GIT_REFLOG_ACTION:+set} ] then -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 6/7] rebase: write better reflog messages
Junio C Hamano gits...@pobox.com writes: Junio C Hamano gits...@pobox.com writes: Excellent question, and I think this illustrates why the recent reroll that uses an approach to use base_reflog_action is not complete and needs further work (to put it mildly). ... That essentially boils down to the very original suggestion I made before Ram introduced the base_reflog_action. So how about doing something like this? Having said all that, although I think the something like this patch is an improvement in that it spells out the rules regarding the use of GIT_REFLOG_ACTION environment variable, which was not documented so far, I think the environment variable is showing its flaws. It was a good mechanism in simpler times, back when git commit, git fetch and git merge were its primary users. They didn't do many ref updates, and having a way to record that this update was done by a 'merge' command initiated by the end user was perfectly adequate. For a command like rebase that can do many ref updates, having to set a custom message and export the variable in each and every step is cumbersome, and keeping the same prefix across becomes even more so. The $orig_reflog_action used inside git-rebase--interactive is a reasonable local solution for the keeping the same prefix problem, but it is a _local_ solution that does not scale. In the end, it updates the GIT_REFLOG_ACTION variable, so the script has to be very careful to make sure the variable has a sensible value before calling any ref-updating git command. It will have to set it back to $orig_reflog_action if it ever wants to call another scripted Porcelain. Among the C infrastructure, commit, fetch, merge and reset are the only ones that pay attention to GIT_REFLOG_ACTION, and we will be adding checkout to the mix. If we originally did not make the mistake of using GIT_REFLOG_ACTION as a whole message, and instead used it to convey _only_ the prefix (i.e. rebase, am, etc.) to subprocesses in order to remember what the end-user initiated command was, and used a command line argument to give the actual messages, we would have been in much better shape. E.g. a checkout call inside git rebase may become git checkout \ --reflog-message=$GIT_REFLOG_ACTION: detaching \ $onto^0 and nobody other than set_reflog_action shell function would be setting GIT_REFLOG_ACTION variable. Oh well. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: small misspellings fixes
Matthieu Moy matthieu@grenoble-inp.fr writes: Veres Lajos vla...@gmail.com writes: I am trying to convert this pull request: https://github.com/git/git/pull/42 to a proper patch email Use git format-patch and/or git send-email to get the proper formatting. (Sorry If I miss something about the process.) Yes, your patch doesn't have exactly the right format, and you should have Cc-ed Junio (see Documentation/SubmittingPatches in Git's source tree). Other than that, the content of the patch looks good (and actually, at least one of the typos is mine :-( ). Can you resend? Repeating the subject in the body is unnecessary. I'll pick it up from here and will fix up. No need to resend. Thanks. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] peel_onion(): add support for rev^{tag}
Richard Hansen rhan...@bbn.com writes: gitrevisions(7) implies that rev^{tag} should work,... Does it? Is it possible that that should be fixed? What does it even _mean_ to peel something to a TAG? A commit, a tree or a blob cannot be peeled to a tag---none of them can contain a tag. When you have a tag that points at something else, what you have is already a tag, so that-tag^{tag} would be that-tag itself. Even more confusingly, when you have a tag that points at another tag, what does that-outer-tag^{tag} mean? The outer tag itself, or do you need to peel at least once to reveal the inner-tag? What if that inner-tag points at yet another tag? The patch does not touch peel_to_type(), so your answer to the above question seems to be if T is already a tag, T^{tag} is T itself, but then that operation does not look all that useful. Confused... diff --git a/sha1_name.c b/sha1_name.c index 90419ef..68fd0e4 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -677,6 +677,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1) sp++; /* beginning of type name, or closing brace for empty */ if (!strncmp(commit_type, sp, 6) sp[6] == '}') expected_type = OBJ_COMMIT; + else if (!strncmp(tag_type, sp, 3) sp[3] == '}') + expected_type = OBJ_TAG; else if (!strncmp(tree_type, sp, 4) sp[4] == '}') expected_type = OBJ_TREE; else if (!strncmp(blob_type, sp, 4) sp[4] == '}') -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [Request] Git reset should be able to ignore file permissions
Matthieu Moy matthieu@grenoble-inp.fr writes: Alexander Nestorov alexander...@gmail.com writes: Ok, this is how it looks. If everything is ok, I'm sending it to the ML Please, read Documentation/SubmittingPatches (you lack a sign-off and if you think the patch is ready, you should Cc Junio). Also, it's better to have the commit headers directly as mail headers (git send-email is your friend). +Reset only files who's content changed (instead of stat information):: That's still not 100% accurate. Actual mode changes would trigger a rewrite of the file. Perhaps stg like Reset only files which actually changed (not those with only stat information change):: (Sorry for nitpicking so much) I do not think the above clarifies anything to be of much help. If you _know_ what actually changed means, i.e. either contents or the executable-ness changed, then (not those ...) does not help you at all. If you don't, then only stat information change will invite I did chmod -x and the file does not have any actual change. confusion. If this addition is to help people who do not know what actually changed means, that part needs to be clarified, no? -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: accessing oldest reflog entry with ref@{N}?
SZEDER GƔbor sze...@ira.uka.de writes: $ git log --oneline -1 master@{1} fatal: Log for 'master' only has 1 entries. Annoyed, I just copy-pasted the sha and got the job done. However, I wonder why it didn't worked. 'git reflog' didn't print master@{1} or any message for the oldest entry, but I can live without that. There lies your answer, no? Each of the log entry records this was before, and this is after the change. ref@{0} reads from the after field of 0-th (from the end) entry. ref@{1} reads from the after field of 1-st (again from the end) entry. ref@{N} reads from the after field of N-th (again from the end) entry. Notice that nowhere in the above sequence we read from before field. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] diff: add --ignore-blank-lines option
The goal of the patch is to introduce the GNU diff -B/--ignore-blank-lines as closely as possible. The short option is not available because it's already used for break-rewrites. When this option is used, git-diff will not create hunks that simply add or remove empty lines, but will still show empty lines addition/suppression if they are close enough to valuable changes. There are two differences between this option and GNU diff -B option: - GNU diff doesn't have --inter-hunk-context, so this must be handled - The following sequence looks like a bug (context is displayed twice): $ seq 5 file1 $ cat EOF file2 change 1 2 3 4 5 change EOF $ diff -u -B file1 file2 --- file1 2013-06-08 22:13:04.471517834 +0200 +++ file2 2013-06-08 22:13:23.275517855 +0200 @@ -1,5 +1,7 @@ +change 1 2 + 3 4 5 @@ -3,3 +5,4 @@ 3 4 5 +change So here is a more thorough description of the option: - real changes are interesting - blank lines that are close enough (less than context size) to interesting changes are considered interesting (recursive definition) - context lines are used around each hunk of interesting changes - If two hunks are separated by less than inter-hunk-context, they will be merged into one. The implementation does the interesting changes selection in a single pass. Signed-off-by: Antoine Pelisse apeli...@gmail.com --- Changes since last version: - changes variable has been renamed to ignored - lxch == xchp is used instead of setting changes to a specific value (ULONG_MAX) - Fixed commit message - Fixed bug we discussed earlier: I added a new else if branch to handle that specific case (short-cut the bug) I'm unfortunately duplicating some logic, but I don't see any way out of this. - Added a test for the bug Documentation/diff-options.txt |3 + diff.c |2 + t/t4015-diff-whitespace.sh | 345 xdiff/xdiff.h |2 + xdiff/xdiffi.c | 29 +++- xdiff/xdiffi.h |1 + xdiff/xemit.c | 49 +- xdiff/xemit.h |2 +- xdiff/xutils.c | 13 ++ xdiff/xutils.h |1 + 10 files changed, 439 insertions(+), 8 deletions(-) diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index b8a9b86..4e042d9 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -439,6 +439,9 @@ endif::git-format-patch[] differences even if one line has whitespace where the other line has none. +--ignore-blank-lines:: + Ignore changes whose lines are all blank. + --inter-hunk-context=lines:: Show the context between diff hunks, up to the specified number of lines, thereby fusing hunks that are close to each other. diff --git a/diff.c b/diff.c index f0b3e7c..208094f 100644 --- a/diff.c +++ b/diff.c @@ -3593,6 +3593,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE); else if (!strcmp(arg, --ignore-space-at-eol)) DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL); + else if (!strcmp(arg, --ignore-blank-lines)) + DIFF_XDL_SET(options, IGNORE_BLANK_LINES); else if (!strcmp(arg, --patience)) options-xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF); else if (!strcmp(arg, --histogram)) diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh index cc3db13..3fb4b97 100755 --- a/t/t4015-diff-whitespace.sh +++ b/t/t4015-diff-whitespace.sh @@ -142,6 +142,351 @@ EOF git diff --ignore-space-at-eol out test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out' +test_expect_success 'ignore-blank-lines: only new lines' ' + test_seq 5 x + git update-index x + test_seq 5 | sed /3/i \\ + x + git diff --ignore-blank-lines out + expect + test_cmp out expect +' + +test_expect_success 'ignore-blank-lines: only new lines with space' ' + test_seq 5 x + git update-index x + test_seq 5 | sed /3/i \ x + git diff -w --ignore-blank-lines out + expect + test_cmp out expect +' + +test_expect_success 'ignore-blank-lines: after change' ' + cat -\EOF x + 1 + 2 + + 3 + 4 + 5 + + 6 + 7 + EOF + git update-index x + cat -\EOF x + change + + 1 + 2 + 3 + 4 + 5 + 6 + + 7 + EOF + git diff --inter-hunk-context=100 --ignore-blank-lines out.tmp + cat -\EOF expected + diff --git a/x b/x + --- a/x + +++ b/x + @@ -1,6 +1,7 @@ + +change + + +1 +2 + - +3 +4 +5 + EOF +
Re: [PATCH v2 00/12] Fix some reference-related races
On Wed, Jun 19, 2013 at 09:51:21AM +0200, Michael Haggerty wrote: Re-roll of mh/ref-races. Thanks to Peff, Junio, and Ramsay for reviewing v1. Thanks. I just read through them again. Everything looks good to me. Patches 10 and 11 are missing my signoff, but obviously: Signed-off-by: Jeff King p...@peff.net The last patch is still optional--it avoids a little bit of work when rewriting the packed-refs file, but relies on the stat-based freshness check not giving a false negative. I don't have a real problem with it, but given the cygwin confusions that Ramsay mentioned, maybe it is better to hold back on it for now? It sounds like the cygwin problems go the other way (false positives instead of false negatives). -Peff -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] glossary: add 'treeish' as a synonym for 'tree-ish'
On 2013-06-19 13:09, Junio C Hamano wrote: Richard Hansen rhan...@bbn.com writes: The documentation contains a mix of the two spellings, and including both makes it possible for users to search the glossary with their spelling of choice. Is it an option to instead find dashless form in our documentation and turn all of them into tree-ish form with a dash? I personally find it cleaner that way. I can s/treeish/tree-ish/g, although I'd still like to keep 'treeish' in the glossary so that people can find it when they search for the misspelled version. Perhaps something like: -[[def_tree-ish]]tree-ish:: +[[def_tree-ish]]tree-ish (sometimes misspelled treeish):: would be satisfactory? While we're on the topic, do you have a preference for commit-ish vs. committish? Grepping the code shows comittish to be the overwhelming favorite, but it's inconsistent with tree-ish. -Richard Signed-off-by: Richard Hansen rhan...@bbn.com --- Documentation/glossary-content.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index db2a74d..01365d9 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -486,7 +486,7 @@ should not be combined with other pathspec. with refs to the associated blob and/or tree objects. A def_tree,tree is equivalent to a def_directory,directory. -[[def_tree-ish]]tree-ish:: +[[def_tree-ish]]tree-ish (also treeish):: A def_ref,ref pointing to either a def_commit_object,commit object, a def_tree_object,tree object, or a def_tag_object,tag object pointing to a tag or commit or tree object. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
On 2013-06-19 13:14, Junio C Hamano wrote: object-type-ish does not have anything to do with a ref. Even when an object is dangling in your object store without being reachable from any of your refs, it keeps its own ish-ness. Ah, so your personal definition of ref matches my personal definition of ref, and this definition doesn't match gitglossary(7). :) ish-ness is a property of the object itself. * A commit object has a single top-level tree, and when a command wants a tree object, you can often pass it a commit (historically some commands were more strict and refused to work on a commit when they wanted a tree). In other words, a commit can be used in place for a tree. A commit object is a tree-ish. * A tag object, when it points (recursively) at a commit object, can often be used in place for a commit object. Such a tag object is a commit-ish. * A tag object, when it points (recursively) at a tree object, can often be used in place for a tree object. Such a tag object is a tree-ish. Note that such a tag object cannot be a commit-ish. I agree with all of this; the issue is the definition of ref in gitglossary(7). That definition should be fixed. In the meantime, I'll rework the patch series to avoid using the word ref when defining committish and tree-ish. -Richard -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 04/12] refs: implement simple transactions for the packed-refs file
Michael Haggerty mhag...@alum.mit.edu writes: Handle simple transactions for the packed-refs file at the packed_ref_cache level via new functions lock_packed_refs(), commit_packed_refs(), and rollback_packed_refs(). Only allow the packed ref cache to be modified (via add_packed_ref()) while the packed refs file is locked. Change clone to add the new references within a transaction. Signed-off-by: Michael Haggerty mhag...@alum.mit.edu --- builtin/clone.c | 7 - refs.c | 83 ++--- refs.h | 27 +-- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/builtin/clone.c b/builtin/clone.c index 66bff57..b0c000a 100644 --- a/builtin/clone.c +++ b/builtin/clone.c @@ -489,17 +489,22 @@ static struct ref *wanted_peer_refs(const struct ref *refs, return local_refs; } +static struct lock_file packed_refs_lock; + static void write_remote_refs(const struct ref *local_refs) { const struct ref *r; + lock_packed_refs(packed_refs_lock, LOCK_DIE_ON_ERROR); + for (r = local_refs; r; r = r-next) { if (!r-peer_ref) continue; add_packed_ref(r-peer_ref-name, r-old_sha1); } - pack_refs(PACK_REFS_ALL); + if (commit_packed_refs()) + die_errno(unable to overwrite old ref-pack file); } The calling convention used here looks somewhat strange. You allow callers to specify which lock-file structure is used when locking, but when you are done, commit_packed_refs() does not take any parameter. lock_packed_refs() make the singleton in-core packed-ref-cache be aware of which lock it is under, so commit_packed_refs() does not need to be told (the singleton already knows what lockfile is in effect), so I am not saying the code is broken, though. Does the caller need to even have an access to this lock_file instance? static void write_followtags(const struct ref *refs, const char *msg) diff --git a/refs.c b/refs.c index 373d95b..ad73251 100644 --- a/refs.c +++ b/refs.c @@ -808,6 +808,13 @@ static int is_refname_available(const char *refname, const char *oldrefname, struct packed_ref_cache { struct ref_entry *root; + + /* + * Iff the packed-refs file associated with this instance is + * currently locked for writing, this points at the associated + * lock (which is owned by somebody else). + */ + struct lock_file *lock; }; /* @@ -829,6 +836,8 @@ static struct ref_cache { static void clear_packed_ref_cache(struct ref_cache *refs) { if (refs-packed) { + if (refs-packed-lock) + die(internal error: packed-ref cache cleared while locked); free_ref_entry(refs-packed-root); free(refs-packed); refs-packed = NULL; @@ -1038,7 +1047,12 @@ static struct ref_dir *get_packed_refs(struct ref_cache *refs) void add_packed_ref(const char *refname, const unsigned char *sha1) { - add_ref(get_packed_refs(ref_cache), + struct packed_ref_cache *packed_ref_cache = + get_packed_ref_cache(ref_cache); + + if (!packed_ref_cache-lock) + die(internal error: packed refs not locked); + add_ref(get_packed_ref_dir(packed_ref_cache), create_ref_entry(refname, sha1, REF_ISPACKED, 1)); } @@ -2035,6 +2049,52 @@ static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data) return 0; } +int lock_packed_refs(struct lock_file *lock, int flags) +{ + struct packed_ref_cache *packed_ref_cache; + + /* Discard the old cache because it might be invalid: */ + clear_packed_ref_cache(ref_cache); + if (hold_lock_file_for_update(lock, git_path(packed-refs), flags) 0) + return -1; + /* Read the current packed-refs while holding the lock: */ + packed_ref_cache = get_packed_ref_cache(ref_cache); + packed_ref_cache-lock = lock; + return 0; +} + +int commit_packed_refs(void) +{ + struct packed_ref_cache *packed_ref_cache = + get_packed_ref_cache(ref_cache); + int error = 0; + + if (!packed_ref_cache-lock) + die(internal error: packed-refs not locked); + write_or_die(packed_ref_cache-lock-fd, + PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER)); + + do_for_each_entry_in_dir(get_packed_ref_dir(packed_ref_cache), + 0, write_packed_entry_fn, + packed_ref_cache-lock-fd); + if (commit_lock_file(packed_ref_cache-lock)) + error = -1; + packed_ref_cache-lock = NULL; + return error; +} + +void rollback_packed_refs(void) +{ + struct packed_ref_cache *packed_ref_cache = + get_packed_ref_cache(ref_cache); + + if (!packed_ref_cache-lock) + die(internal
Re: [PATCH 1/6] t/t5528-push-default: remove redundant test_config lines
Ramkumar Ramachandra artag...@gmail.com writes: The line test_config push.default upstream appears unnecessarily in two tests, as the final test_push_failure sets push.default before pushing anyway. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- t/t5528-push-default.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index 4736da8..69ce6bf 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -48,7 +48,6 @@ test_expect_success 'upstream pushes to configured upstream' ' test_expect_success 'upstream does not push on unconfigured remote' ' git checkout master test_unconfig branch.master.remote - test_config push.default upstream test_commit three test_push_failure upstream ' @@ -57,7 +56,6 @@ test_expect_success 'upstream does not push on unconfigured branch' ' git checkout master test_config branch.master.remote parent1 test_unconfig branch.master.merge - test_config push.default upstream test_commit four test_push_failure upstream ' Makes sense, but I wonder if the only remaining test_config should also be eradicated in the test after this one. test_expect_success 'upstream does not push when remotes do not match' ' git checkout master test_config branch.master.remote parent1 test_config branch.master.merge refs/heads/foo test_config push.default upstream test_commit five test_must_fail git push parent2 ' It uses test_must_fail but that is only because test_push_failure is not equipped to handle anything other than git push without arguments. If the helper were updated to do something like this: strategy=$1; shift ... test_must_fail git -c push.default=$strategy push $@ then test_config push.default here can be removed and all the tests will end with test_push_success or test_push_failure. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: accessing oldest reflog entry with ref@{N}?
On Wed, Jun 19, 2013 at 11:48:01AM -0700, Junio C Hamano wrote: SZEDER GƔbor sze...@ira.uka.de writes: $ git log --oneline -1 master@{1} fatal: Log for 'master' only has 1 entries. Annoyed, I just copy-pasted the sha and got the job done. However, I wonder why it didn't worked. 'git reflog' didn't print master@{1} or any message for the oldest entry, but I can live without that. There lies your answer, no? Each of the log entry records this was before, and this is after the change. ref@{0} reads from the after field of 0-th (from the end) entry. ref@{1} reads from the after field of 1-st (again from the end) entry. ref@{N} reads from the after field of N-th (again from the end) entry. Notice that nowhere in the above sequence we read from before field. In general, the before from entry @{N} should be the same as the after of @{N+1}. Of course this is not always the case for various reasons, the most common of which I think are: 1. Buggy scripts which do not provide a reflog reason for their call to git-update-ref, and therefore update the ref without writing a reflog entry. 2. A git-gc will expire entries which point to unreachable objects much earlier, which can create holes in the reflog. So it is certainly not correct to say we do not have a master@{1} entry, but we know that the 'before' entry of master@{0} must point to the same thing. But it is very often a good guess. I wonder if there should be some simple way to expose that value as an @{}-selector. Perhaps ref@{0.before} or something? -Peff -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/6] config doc: rewrite push.default section
Ramkumar Ramachandra artag...@gmail.com writes: push.default:: + Defines the action `git push` should take if no refspec is + explicitly given. Different values are well-suited for + specific workflows; for instance, in a purely central workflow + (i.e. the fetch source is equal to the push destination), + `upstream` is probably what you want. Possible values are: + -- -* `nothing` - do not push anything. -* `matching` - push all branches having the same name in both ends. - This is for those who prepare all the branches into a publishable - shape and then push them out with a single command. It is not - appropriate for pushing into a repository shared by multiple users, - since locally stalled branches will attempt a non-fast forward push - if other users updated the branch. - + - This is currently the default, but Git 2.0 will change the default - to `simple`. -* `upstream` - push the current branch to its upstream branch - (`tracking` is a deprecated synonym for this). - With this, `git push` will update the same remote ref as the one which - is merged by `git pull`, making `push` and `pull` symmetrical. - See branch.name.merge for how to configure the upstream branch. +* `nothing` - do not push anything (error out) unless a refspec is + explicitly given. Very safe, but not very convenient. Drop the last one, that does not add any value to the description. + +* `current` - push the current branch to update a branch with the same + name on the receiving end. Works in both central and non-central + workflows. Equivalent to pushing the refspec $branch ($branch is + the name of the current branch). I do not think this is a place to teach how various refspecs are spelled, but if you want to, then giving a complete command line would be more appropriate. Otherwise I'd suggest dropping everything after Equivalent to +* `upstream` - push the current branch to a branch with the name + branch.$branch.merge on the receiving end, and error out if the push + destination is not the same as branch.$branch.remote. While the above may be technically accurate, a mechanical definition help readers who read this for the first time may not be very helpful. What does the operation mean? push the current branch back to the branch whose changes are usually integrated into the current branch with git pull (which is called @{upstream}). this mode only makes sense if you are pushing to the same repository you would normally pull from (i.e. central workflow). * `simple` - like `upstream`, but refuses to push if the upstream branch's name is different from the local one. This is the safest option and is well-suited for beginners. It will become the default in Git 2.0. OK. +* `matching` - push all branches having the same name on both ends + (essentially ignoring all newly created local branches). That misses the 'essense' of 'matching' by a wide margin, as newly created does not have anything to do with it. Topic branches you decided not to push long time ago and haven't pushed out so far will not suddenly get pushed with git push, either. Think of it this way. Among your local branches, there are classes of branches that: (1) you would want to push now, (2) you would want to push when they are done, and (3) you would never want to push. Other push only single branch modes make this distinction by limiting the push to only the first class (those you would want to push now), but it further limits that set to a single branch, which is the current one. It is up to you to differentiate class 2+3 (those you do not want to push now) from class 1 (the single one you do want to push) and you indicate that choice by running 'git push' only when you are on the branch you want to push out. The 'matching' mode allows you to configure by having the other side remember which ones are in the class 1 (i.e. those that you will push out when you say 'git push'). Instead of keeping a list of branches to be pushed in local configuration variable, you use the set of branches your publishing point has. It has a limitation that you are not allowed to have the second category (i.e. at this point of running 'git push' they are not ready to be pushed out), though. Perhaps ... on both ends. This makes the repository you are pushing to remember the set of branches that will be pushed out (e.g. if you always push 'maint' and 'master' there and no other branches, the repository you push to will have these two branches, and your local 'maint' and 'master' will be pushed there). To use this mode effectively, you have to make sure _all_ the branches you would push out are ready to be pushed out before running 'git push', as the whole point of this mode is to allow you to push all of the branches in one go.
Re: [PATCH 3/6] push: change `simple` to accommodate triangular workflows
Ramkumar Ramachandra artag...@gmail.com writes: When remote.pushdefault or branch.name.pushremote is set (a triangular workflow feature), master@{u} != origin, and push.default is set to `upstream` or `simple`: $ git push fatal: You are pushing to remote 'origin', which is not the upstream of your current branch 'master', without telling me what to push to update which remote branch. Unfortunately, in the case of `upstream`, the very name indicates that it is only suitable for use in central workflows; let us not even attempt to give it a new meaning in triangular workflows, and error out as usual. Sensible. However, the `simple` does not have this problem: it is poised to be the default for Git 2.0, and we would definitely like it to do something sensible in triangular workflows. Decouple `simple` from `upstream` completely, and change it to mean `current` with a safety feature: a `push` and `pull` should not be asymmetrical in the special case of central workflows. Double negation confused my parser. 'push' and 'pull' should be kept symmetrical in central workflows? +* `simple` - a safer version of `current`; push the current branch to + update a branch with the same name on the receiving end, with a + safety feature: in central workflows, error out if + branch.$branch.merge is set and not equal to $branch, If branch.$branch.merge is _not_ set, what happens in the current code, and what should happen? + to make sure + that a `push` and `push` are never asymmetrical. It will become the + default in Git 2.0. Ditto. * `matching` - push all branches having the same name on both ends (essentially ignoring all newly created local branches). diff --git a/builtin/push.c b/builtin/push.c index 2d84d10..d8d27d9 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -120,6 +120,25 @@ static const char message_detached_head_die[] = \n git push %s HEAD:name-of-remote-branch\n); +static void setup_push_simple(struct remote *remote) +{ + struct branch *branch = branch_get(NULL); + if (!branch) + die(_(message_detached_head_die), remote-name); OK. + if (!branch-merge_nr || !branch-merge || !branch-remote_name) + /* No upstream configured */ + goto end; Without any configuration the current branch is pushed out, which loosens the safety we implemented in the current 'safer upstream'. I am not convinced this is a good change. I am not convinced this is a bad change, either, yet, but this loosening smells bad. diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index 69ce6bf..e54dd02 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -85,7 +85,7 @@ test_expect_success 'push from/to new branch with current creates remote branch' test_expect_success 'push to existing branch, with no upstream configured' ' test_config branch.master.remote repo1 git checkout master - test_push_failure simple + test_push_success simple master test_push_failure upstream ' Likewise. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 4/6] push: remove dead code in setup_push_upstream()
Ramkumar Ramachandra artag...@gmail.com writes: Now that simple has been decoupled from upstream in setup_push_simple(), remove the dead code in setup_push_upstream(). Good. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- builtin/push.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/builtin/push.c b/builtin/push.c index d8d27d9..783bacf 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -139,7 +139,7 @@ end: add_refspec(branch-name); } -static void setup_push_upstream(struct remote *remote, int simple) +static void setup_push_upstream(struct remote *remote) { struct strbuf refspec = STRBUF_INIT; struct branch *branch = branch_get(NULL); @@ -161,8 +161,6 @@ static void setup_push_upstream(struct remote *remote, int simple) your current branch '%s', without telling me what to push\n to update which remote branch.), remote-name, branch-name); - if (simple strcmp(branch-refname, branch-merge[0]-src)) - die_push_simple(branch, remote); strbuf_addf(refspec, %s:%s, branch-name, branch-merge[0]-src); add_refspec(refspec.buf); @@ -211,7 +209,7 @@ static void setup_default_push_refspecs(struct remote *remote) break; case PUSH_DEFAULT_UPSTREAM: - setup_push_upstream(remote, 0); + setup_push_upstream(remote); break; case PUSH_DEFAULT_CURRENT: -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] peel_onion(): add support for rev^{tag}
On 2013-06-19 14:38, Junio C Hamano wrote: Richard Hansen rhan...@bbn.com writes: gitrevisions(7) implies that rev^{tag} should work,... Does it? Is it possible that that should be fixed? Depends on whether you think ^{tag} is a useful feature or not; see below. What does it even _mean_ to peel something to a TAG? It's the same as peeling something to any other object type: If the object is that type, done. Otherwise dereference and try again. If it can't be dereferenced, barf. A commit, a tree or a blob cannot be peeled to a tag---none of them can contain a tag. Right, so all of those would barf. When you have a tag that points at something else, what you have is already a tag, so that-tag^{tag} would be that-tag itself. Exactly, just like object^{object} is object itself. Even more confusingly, when you have a tag that points at another tag, what does that-outer-tag^{tag} mean? The outer tag itself, or do you need to peel at least once to reveal the inner-tag? What if that inner-tag points at yet another tag? The patch does not touch peel_to_type(), so your answer to the above question seems to be if T is already a tag, T^{tag} is T itself, but then that operation does not look all that useful. Barfing on non-tags is the feature this adds. It's otherwise useless, just like object^{object} is useless except to barf when object doesn't exist. It's a sometimes-convenient way to assert that an object specifier refers to a tag object and not something else. For example, instead of: fatal() { printf %s\\n ERROR: $* 2; exit 1; } type=$(git cat-file -t $1) || fatal $1 is not a valid object [ ${type} = tag ] || fatal $1 is not a tag object use $1 here you can do: use $1^{tag} here -Richard Confused... diff --git a/sha1_name.c b/sha1_name.c index 90419ef..68fd0e4 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -677,6 +677,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1) sp++; /* beginning of type name, or closing brace for empty */ if (!strncmp(commit_type, sp, 6) sp[6] == '}') expected_type = OBJ_COMMIT; +else if (!strncmp(tag_type, sp, 3) sp[3] == '}') +expected_type = OBJ_TAG; else if (!strncmp(tree_type, sp, 4) sp[4] == '}') expected_type = OBJ_TREE; else if (!strncmp(blob_type, sp, 4) sp[4] == '}') -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] glossary: add 'treeish' as a synonym for 'tree-ish'
On 2013-06-19 13:09, Junio C Hamano wrote: Richard Hansen rhan...@bbn.com writes: The documentation contains a mix of the two spellings, and including both makes it possible for users to search the glossary with their spelling of choice. Is it an option to instead find dashless form in our documentation and turn all of them into tree-ish form with a dash? I personally find it cleaner that way. My preference is treeish and committish (instead of tree-ish and commit-ish) because those are the spellings used in the source code. -Richard Signed-off-by: Richard Hansen rhan...@bbn.com --- Documentation/glossary-content.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt index db2a74d..01365d9 100644 --- a/Documentation/glossary-content.txt +++ b/Documentation/glossary-content.txt @@ -486,7 +486,7 @@ should not be combined with other pathspec. with refs to the associated blob and/or tree objects. A def_tree,tree is equivalent to a def_directory,directory. -[[def_tree-ish]]tree-ish:: +[[def_tree-ish]]tree-ish (also treeish):: A def_ref,ref pointing to either a def_commit_object,commit object, a def_tree_object,tree object, or a def_tag_object,tag object pointing to a tag or commit or tree object. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] Documentation: Update 'linux-2.6.git' - 'linux.git'
On Wed, Jun 19, 2013 at 10:07:24AM -0700, Junio C Hamano wrote: W. Trevor King wk...@tremily.us writes: diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt index a0727d7..8e5260f 100644 --- a/Documentation/git-clone.txt +++ b/Documentation/git-clone.txt @@ -274,7 +274,7 @@ $ git clone --bare -l /home/proj/.git /pub/scm/proj.git * Create a repository on the kernel.org machine that borrows from Linus: + -$ git clone --bare -l -s /pub/scm/.../torvalds/linux-2.6.git \ +$ git clone --bare -l -s /pub/scm/.../torvalds/linux.git \ /pub/scm/.../me/subsys-2.6.git Aside from s|subsys-2.6|subsys| David already mentioned, I think it is a lot saner to remove this particular example. Nobody runs shell on k.org machines these days, and local borrowing -l -s is already shown in another example. Also you seem to have missed another linux-2.6 my2.6 clone in the first example. Between the nfs-2.6 examples I mentioned earlier, the my2.6 clone here, and the: $ git clone --reference my2.6 \ git://git.kernel.org/pub/scm/.../linux-2.7 \ my2.7 example listed later in git-clone.txt, I think we're trying to push linux.git examples too far ;). However, I can't think of a simple example for --reference that doesn't drag in a longer discussion to motivate shared object repositories. I'll hunt through the rest of the docs looking for other examples I can reuse. I think any doc rewrites should be outside the scope of this patch, which should just replace references to linux-2.6.git with linux.git (as it does). Further cleanups to remove references to the NFS and my2.{6,7} stuff and replace them with alternative examples can come as follow-up patches in v2 of this series. Does that sound reasonable? Should the size updates from 2/2 (user-manual: Update download size for Git and the kernel) go into the reroll, or have they been picked up in a separate branch? Cheers, Trevor -- This email may be signed or encrypted with GnuPG (http://www.gnupg.org). For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy signature.asc Description: OpenPGP digital signature
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
Richard Hansen rhan...@bbn.com writes: On 2013-06-19 13:14, Junio C Hamano wrote: object-type-ish does not have anything to do with a ref. Even when an object is dangling in your object store without being reachable from any of your refs, it keeps its own ish-ness. Ah, so your personal definition of ref matches my personal definition of ref, and this definition doesn't match gitglossary(7). :) Huh? The only thing I I said was that *-ish does not have anything to do with a ref. I didn't say anything about definition of ref. You are the one who brought ref into description of *-ish, with this: +[[def_committish]]committish (also commit-ish):: + A def_ref,ref pointing to an def_object,object that + can be recursively dereferenced to a All I am saying is that an object does not have to be pointed by any ref to be any-ish. ish-ness is an attribute of an object, not an ref. You do not say refs/heads/master (which is a ref) is a commit-ish or a tree-ish. The object pointed at by that ref is always a commit and is a commit-ish and a tree-ish. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] Documentation: Update 'linux-2.6.git' - 'linux.git'
W. Trevor King wk...@tremily.us writes: I think any doc rewrites should be outside the scope of this patch, which should just replace references to linux-2.6.git with linux.git (as it does). OK. Should the size updates from 2/2 (user-manual: Update download size for Git and the kernel) go into the reroll, or have they been picked up in a separate branch? I think 2/2 is fine. Here is what I'll queue. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index e831cc2..1cbf5af 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -57,10 +57,10 @@ download a copy of an existing repository. If you don't already have a project in mind, here are some interesting examples: - # Git itself (approx. 10MB download): + # Git itself (approx. 40MB download): $ git clone git://git.kernel.org/pub/scm/git/git.git - # the Linux kernel (approx. 150MB download): -$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + # the Linux kernel (approx. 640MB download): +$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git The initial clone may be time-consuming for a large project, but you -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/4] glossary: add 'treeish' as a synonym for 'tree-ish'
Richard Hansen rhan...@bbn.com writes: Perhaps something like: -[[def_tree-ish]]tree-ish:: +[[def_tree-ish]]tree-ish (sometimes misspelled treeish):: would be satisfactory? If it is a misspelling, I do not think we need to list both. An entry tree-ish can be found if you were looking for treeish. If it is not, then sometimes misspelled should perhaps is better aka. I do not personally have a very strong preference between the dashed and dashless forms, but if I really have to pick one over the other, I would probably go with tree-ish, commit-ish, as these are not real words. I do have mild preference of not listing both to keep things shorter and cleaner. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 5/6] t/t5528-push-default: generalize test_push_*
Ramkumar Ramachandra artag...@gmail.com writes: The setup creates two bare repositories: repo1 and repo2, but test_push_commit() hard-codes checking in repo1 for the actual output. Generalize it and its caller, test_push_success(), to optionally accept a third argument to specify the name of the repository to check for actual output. We will use this in the next patch. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- Makes sense. t/t5528-push-default.sh | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index e54dd02..b599186 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -15,17 +15,19 @@ test_expect_success 'setup bare remotes' ' # $1 = local revision # $2 = remote revision (tested to be equal to the local one) +# $3 = [optional] repo to check for actual output (repo1 by default) check_pushed_commit () { git log -1 --format='%h %s' $1 expect - git --git-dir=repo1 log -1 --format='%h %s' $2 actual + git --git-dir=${3:-repo1} log -1 --format='%h %s' $2 actual test_cmp expect actual } # $1 = push.default value # $2 = expected target branch for the push +# $3 = [optional] repo to check for actual output (repo1 by default) test_push_success () { git -c push.default=$1 push - check_pushed_commit HEAD $2 + check_pushed_commit HEAD $2 $3 } # $1 = push.default value -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 6/6] t/t5528-push-default: test pushdefault workflows
Ramkumar Ramachandra artag...@gmail.com writes: Introduce test_pushdefault_workflows(), and test that all push.default modes work with central and triangular workflows as expected. Signed-off-by: Ramkumar Ramachandra artag...@gmail.com --- t/t5528-push-default.sh | 36 1 file changed, 36 insertions(+) diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh index b599186..eabc09d 100755 --- a/t/t5528-push-default.sh +++ b/t/t5528-push-default.sh @@ -39,6 +39,26 @@ test_push_failure () { test_cmp expect actual } +# $1 = success or failure +# $2 = push.default value +# $3 = branch to check for actual output (master or foo) +# $4 = [optional] switch to triangular workflow +test_pushdefault_workflow () { + workflow=central + pushdefault=parent1 + if test -n ${4-}; then + workflow=triangular + pushdefault=parent2 + fi +test_expect_success push.default = $2 $1 in $workflow workflows + test_config branch.master.remote parent1 + test_config branch.master.merge refs/heads/foo + test_config remote.pushdefault $pushdefault + test_commit commit-for-$2${4+-triangular} + test_push_$1 $2 $3 ${4+repo2} + Please indent the above; it is hard to spot where the actual test begins and ends otherwise. +} + test_expect_success 'upstream pushes to configured upstream' ' git checkout master test_config branch.master.remote parent1 @@ -115,4 +135,20 @@ test_expect_success 'push to existing branch, upstream configured with different test_cmp expect-other-name actual-other-name ' +## test_pushdefault_workflow() arguments: +# $1 = success or failure +# $2 = push.default value +# $3 = branch to check for actual output (master or foo) +# $4 = [optional] switch to triangular workflow What happens in current/upstream/simple modes is affected by the current branch, but it is unclear on what branch do these all run at the first glance. It would be helpful to add a comment here that says what the starting condition is, something like: # We are on 'master', which integrates with 'foo' from parent1 # Both parent1 and parent2 repositories have 'master' and 'foo' # branches. here. It took me a while to tell what some of these comments wanted to say without such a comment. +test_pushdefault_workflow success current master # breaks push/pull symmetry On 'master', push.default = current and we are in central workflow. Because we do not use upstream but current, that deliberately breaks the symmetry. We make sure that 'master' is updated. Looks correct. +test_pushdefault_workflow success upstream foo# preserves push/pull symmetry We use 'upstream'; current branch is set to integrate with 'foo' and that is what is updated. Looks good. +test_pushdefault_workflow failure simple master # errors out on asymmetry Simple is a safer form of 'current' in the central workflow. The current branch is set to integrate with 'foo', which is different name from the current branch'es name 'master', and the push fails. Looks correct, but do we want to make sure 'foo' is not updated here as well? +test_pushdefault_workflow success matching master # always works This also should update 'foo'; do we want to make sure that happens too? Otherwise we won't be able to tell between matching and current. +test_pushdefault_workflow success current master triangular # always works OK. +test_pushdefault_workflow failure upstream foo triangular# always errors out OK. +test_pushdefault_workflow success simple master triangular # works like current OK, because in triangular it is like current. +test_pushdefault_workflow success matching master triangular # always works OK. As this step adds a useful helper function for testing, it appears to me that the helper can and should check the postcondition more carefully, e.g. not just making sure what should be updated is updated, but what should not be updated is not touched. Other than that, looks fine to me. + test_done -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] diff: add --ignore-blank-lines option
Antoine Pelisse apeli...@gmail.com writes: So here is a more thorough description of the option: - real changes are interesting - blank lines that are close enough (less than context size) to interesting changes are considered interesting (recursive definition) - context lines are used around each hunk of interesting changes - If two hunks are separated by less than inter-hunk-context, they will be merged into one. Thanks; will replace what is queued in 'pu'. Let's advance this version to 'next' soonish. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
On 2013-06-19 17:05, Junio C Hamano wrote: Richard Hansen rhan...@bbn.com writes: On 2013-06-19 13:14, Junio C Hamano wrote: object-type-ish does not have anything to do with a ref. Even when an object is dangling in your object store without being reachable from any of your refs, it keeps its own ish-ness. Ah, so your personal definition of ref matches my personal definition of ref, and this definition doesn't match gitglossary(7). :) Huh? The only thing I I said was that *-ish does not have anything to do with a ref. I didn't say anything about definition of ref. The phrase when an object is dangling in your object store without being reachable from any of your refs implies something about your definition of a ref that is inconsistent with gitglossary(7). See below. You are the one who brought ref into description of *-ish, with this: +[[def_committish]]committish (also commit-ish):: +A def_ref,ref pointing to an def_object,object that +can be recursively dereferenced to a And I did that to be consistent with the definition of tree-ish, which currently says: tree-ish A ref pointing to either a commit object, a tree object, or a tag object pointing to a tag or commit or tree object. Notice the term ref in the above definition. This definition says that a tree-ish is a particular kind of ref -- NOT a property of an object as you claim. I'm not saying you're wrong -- I actually agree with you completely -- I'm just saying that your definition of ref doesn't match the definition of ref in gitglossary(7). The current definition of ref says: ref A 40-byte hex representation of a SHA-1 or a name that denotes a particular object. They may be stored in a file under $GIT_DIR/refs/ directory, or in the $GIT_DIR/packed-refs file. Depending on how one interprets name (which is not defined in gitglossary(7)) in the above definition of ref, claiming that master:README is a ref is consistent with gitglossary(7). It is NOT, however, consistent with what you -- or anyone else I know -- think of as a ref. All I am saying is that an object does not have to be pointed by any ref to be any-ish. ish-ness is an attribute of an object, not an ref. You do not say refs/heads/master (which is a ref) is a commit-ish or a tree-ish. The object pointed at by that ref is always a commit and is a commit-ish and a tree-ish. I understand and agree completely and always have. Here's what I'm trying to say: * Given the current definition of ref in gitglossary(7), claiming that a foo-ish is a ref is not entirely incorrect. * If the definition of ref is altered to match the general understanding of a ref, then claiming that a foo-ish is a ref is wrong. Very wrong. I was trying to be minimal and consistent with my changes, but unfortunately it seems like more changes are necessary. When I next have time, I'll send some revised patches to include the following changes: * replace the current definition of ref with something that matches general understanding * eliminate the use of ref in the definitions of tag object, tree object, and tree-ish * create a term that means a thing understood by rev-parse that uniquely identifies an object (perhaps object specifier?) that can be used in gitglossary(7) and elsewhere -Richard -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
Richard Hansen rhan...@bbn.com writes: Here's what I'm trying to say: * Given the current definition of ref in gitglossary(7), claiming that a foo-ish is a ref is not entirely incorrect. Ahh. If you had quoted this a few exchanges ago: [[def_ref]]ref:: A 40-byte hex representation of a def_SHA1,SHA-1 or a name that denotes a particular def_object,object. They may be stored in a file under `$GIT_DIR/refs/` directory, or in the `$GIT_DIR/packed-refs` file. I would have immediately understood what you were trying to say. Sorry about a wasted back-and-forth. The above is an utterly confused explanation. It explains object names and mentions as a sidenote that object names _can_ be held in refs. It does not say what a ref is, in other words. Before 'packed-refs' was introduced, the right definition would have been A file under `$GIT_DIR/refs/` directory that holds an object name. And packed-refs is a way to coalesce such files into a single file to make it easier/faster to access. In today's world (after packed-refs was introduced), probably A name that begins with refs/ (e.g. refs/heads/master) that can point at an object name. The namespace of refs is hierarchical and different subhierarchy is used for different purposes (e.g. the refs/heads/ hierarchy is used to represent local branches). is an appropriate rewrite of the above. If we also want to explain the implementation details of refs, then additionally at the end of the first paragraph, add: ... at an object name, by storing its 40-byte hex representation. They are implemented as either a file in $GIT_DIR/refs/ directory (called loose refs) or an entry in $GIT_DIR/packed-refs file (called packed refs); when a loose ref exists, a packed ref of the same name is ignored. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] misspellings fixes by https://github.com/vlajos/misspell_fixer
Signed-off-by: Veres Lajos vla...@gmail.com --- git-p4.py|2 +- git-svn.perl |2 +- t/t7600-merge.sh |2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/git-p4.py b/git-p4.py index 911bbce..88fcf23 100755 --- a/git-p4.py +++ b/git-p4.py @@ -3168,7 +3168,7 @@ class P4Rebase(Command): if os.system(git update-index --refresh) != 0: die(Some files in your working directory are modified and different than what is in your index. You can use git update-index filename to bring the index up-to-date or stash away all your changes with git stash.); if len(read_pipe(git diff-index HEAD --)) 0: -die(You have uncommited changes. Please commit them before rebasing or stash them away with git stash.); +die(You have uncommitted changes. Please commit them before rebasing or stash them away with git stash.); [upstream, settings] = findUpstreamBranchPoint() if len(upstream) == 0: diff --git a/git-svn.perl b/git-svn.perl index d070de0..4e8275f 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -1246,7 +1246,7 @@ sub cmd_rebase { return; } if (command(qw/diff-index HEAD --/)) { - print STDERR Cannot rebase with uncommited changes:\n; + print STDERR Cannot rebase with uncommitted changes:\n; command_noisy('status'); exit 1; } diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh index 2f70433..460d8eb 100755 --- a/t/t7600-merge.sh +++ b/t/t7600-merge.sh @@ -316,7 +316,7 @@ test_expect_success 'merge c1 with c2 (squash)' ' test_debug 'git log --graph --decorate --oneline --all' -test_expect_success 'unsuccesful merge of c1 with c2 (squash, ff-only)' ' +test_expect_success 'unsuccessful merge of c1 with c2 (squash, ff-only)' ' git reset --hard c1 test_must_fail git merge --squash --ff-only c2 ' -- 1.7.10.4 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
On 2013-06-19 18:36, Junio C Hamano wrote: Ahh. If you had quoted [...] a few exchanges ago I would have immediately understood what you were trying to say. Sorry about that, my bad. In today's world (after packed-refs was introduced), probably A name that begins with refs/ (e.g. refs/heads/master) that can point at an object name. The namespace of refs is hierarchical and different subhierarchy is used for different purposes (e.g. the refs/heads/ hierarchy is used to represent local branches). is an appropriate rewrite of the above. Some thoughts about the above definition: * Aren't HEAD, FETCH_HEAD, ORIG_HEAD also refs? * That definition excludes symrefs. * It may be worthwhile to mention that refs are part of the repository. * Is a ref a name? Or is it the binding of a name to an object/ref? How about: ref A binding of a name to an object or other ref (in which case it is a symref). Refs are stored in the repository. The ref namespace is hierarchical. Different subhierarchies are used for different purposes (e.g. the refs/heads/ hierarchy is used to represent local branches). If we also want to explain the implementation details of refs, then additionally at the end of the first paragraph, add: ... at an object name, by storing its 40-byte hex representation. They are implemented as either a file in $GIT_DIR/refs/ directory (called loose refs) or an entry in $GIT_DIR/packed-refs file (called packed refs); when a loose ref exists, a packed ref of the same name is ignored. It would be good to document this somewhere, but I'm not sure the glossary is the right place for it. Maybe gitrepository-layout(5)? -Richard -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] octopus: fallback on empty tree for ancestor
From: R. Andrew Ohana andrew.oh...@gmail.com This is preferable to just aborting when no common ancestor is found since it handles merges of intersecting branches. This is incredibly useful functionality when consolidating multiple repositories (potentially after using filter-branch to fix paths). See http://stackoverflow.com/questions/10874149. Signed-off-by: R. Andrew Ohana andrew.oh...@gmail.com --- git-merge-octopus.sh | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/git-merge-octopus.sh b/git-merge-octopus.sh index 8643f74..582ae69 100755 --- a/git-merge-octopus.sh +++ b/git-merge-octopus.sh @@ -48,6 +48,7 @@ MRC=$(git rev-parse --verify -q $head) MRT=$(git write-tree) NON_FF_MERGE=0 OCTOPUS_FAILURE=0 +EMPTY_TREE=$(git hash-object -t tree /dev/null) for SHA1 in $remotes do case $OCTOPUS_FAILURE in @@ -67,7 +68,9 @@ do eval pretty_name=\${GITHEAD_$SHA1_UP:-$pretty_name} fi common=$(git merge-base --all $SHA1 $MRC) || - die Unable to find common commit with $pretty_name + # Try with an empty tree if no common ancestor was + # found, since it is common to all trees. + common=$EMPTY_TREE case $LF$common$LF in *$LF$SHA1$LF*) -- 1.8.2.1 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[no subject]
-- hello, Heeft u behoefte aan een lening om uw omstandigheden te helpen? Bent u een zakelijke man of een vrouw? Ben je in een financiƫle stress of U wilt uw eigen bedrijf, maar geld hebt, heb je een lening te starten of nodig hypothekeren om uw schulden te vereffenen, of betalen van je rekeningen of start je eigen bedrijf? zo ja je bent om terug te gaan naar ons met de onderstaande details: Naam: Lening Bedrag dat nodig is: ___ Sex: __ Burgerlijke staat: ___ Land: Staat: __ Leeftijd: __ Plaats: __ Telefoon: _ Thuis Adres: __ Lening Duur: __ maandelijkse Income__ Beroep: __ Doel van de lening: __ Religie: __ Groeten. Mr.Vuurhonge Robert -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/6] push: change `simple` to accommodate triangular workflows
Junio C Hamano gits...@pobox.com writes: Without any configuration the current branch is pushed out, which loosens the safety we implemented in the current 'safer upstream'. I am not convinced this is a good change. I am not convinced this is a bad change, either, yet, but this loosening smells bad. Provided that we would want to keep the Push the current one to the same name but you have to have it set up as your integration source safety for central workflow (which I am starting to think we should), we would want something like this on top of your entire series, I think. The behaviour change can be seen in the revert of one test you made to the test that expects simple to fail due to the safety. This patch is somewhat minimal in that it does not address other issues I raised in the review of the series; it only addresses the simple must be safe issue. builtin/push.c | 60 + t/t5528-push-default.sh | 2 +- 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/builtin/push.c b/builtin/push.c index 783bacf..84c4a90 100644 --- a/builtin/push.c +++ b/builtin/push.c @@ -120,29 +120,11 @@ static const char message_detached_head_die[] = \n git push %s HEAD:name-of-remote-branch\n); -static void setup_push_simple(struct remote *remote) -{ - struct branch *branch = branch_get(NULL); - if (!branch) - die(_(message_detached_head_die), remote-name); - if (!branch-merge_nr || !branch-merge || !branch-remote_name) - /* No upstream configured */ - goto end; - if (branch-merge_nr != 1) - die(_(The current branch %s has multiple upstream branches, - refusing to push.), branch-name); - if (!strcmp(branch-remote_name, remote-name) - strcmp(branch-refname, branch-merge[0]-src)) - /* Central workflow safety feature */ - die_push_simple(branch, remote); -end: - add_refspec(branch-name); -} - -static void setup_push_upstream(struct remote *remote) +static void setup_push_upstream(struct remote *remote, struct branch *branch, + int triangular) { struct strbuf refspec = STRBUF_INIT; - struct branch *branch = branch_get(NULL); + if (!branch) die(_(message_detached_head_die), remote-name); if (!branch-merge_nr || !branch-merge || !branch-remote_name) @@ -156,16 +138,29 @@ static void setup_push_upstream(struct remote *remote) if (branch-merge_nr != 1) die(_(The current branch %s has multiple upstream branches, refusing to push.), branch-name); - if (strcmp(branch-remote_name, remote-name)) + if (triangular) die(_(You are pushing to remote '%s', which is not the upstream of\n your current branch '%s', without telling me what to push\n to update which remote branch.), remote-name, branch-name); + if (push_default == PUSH_DEFAULT_SIMPLE) { + /* Additional safety */ + if (strcmp(branch-refname, branch-merge[0]-src)) + die_push_simple(branch, remote); + } + strbuf_addf(refspec, %s:%s, branch-name, branch-merge[0]-src); add_refspec(refspec.buf); } +static void setup_push_current(struct remote *remote, struct branch *branch) +{ + if (!branch) + die(_(message_detached_head_die), remote-name); + add_refspec(branch-name); +} + static char warn_unspecified_push_default_msg[] = N_(push.default is unset; its implicit value is changing in\n Git 2.0 from 'matching' to 'simple'. To squelch this message\n @@ -190,9 +185,16 @@ static void warn_unspecified_push_default_configuration(void) warning(%s\n, _(warn_unspecified_push_default_msg)); } +static int is_workflow_triagular(struct remote *remote) +{ + struct remote *fetch_remote = remote_get(NULL); + return (fetch_remote != remote); +} + static void setup_default_push_refspecs(struct remote *remote) { - struct branch *branch; + struct branch *branch = branch_get(NULL); + int triangular = is_workflow_triagular(remote); switch (push_default) { default: @@ -205,18 +207,18 @@ static void setup_default_push_refspecs(struct remote *remote) break; case PUSH_DEFAULT_SIMPLE: - setup_push_simple(remote); + if (triangular) + setup_push_current(remote, branch); + else + setup_push_upstream(remote, branch, triangular); break; case PUSH_DEFAULT_UPSTREAM: - setup_push_upstream(remote); + setup_push_upstream(remote, branch, triangular); break; case PUSH_DEFAULT_CURRENT: -
Re: [PATCH 2/4] glossary: define committish (a.k.a. commit-ish)
Richard Hansen rhan...@bbn.com writes: On 2013-06-19 18:36, Junio C Hamano wrote: Ahh. If you had quoted [...] a few exchanges ago I would have immediately understood what you were trying to say. Sorry about that, my bad. In today's world (after packed-refs was introduced), probably A name that begins with refs/ (e.g. refs/heads/master) that can point at an object name. The namespace of refs is hierarchical and different subhierarchy is used for different purposes (e.g. the refs/heads/ hierarchy is used to represent local branches). is an appropriate rewrite of the above. Some thoughts about the above definition: * Aren't HEAD, FETCH_HEAD, ORIG_HEAD also refs? That is a shade of gray. refs are names we use as the starting point to construct extended SHA-1 expressions to refer to objects, and in that sense they are. It would be complete to mention these as special cases. * That definition excludes symrefs. True. ... that can directly point at an object, or point at another ref (the latter is called a symbolic ref). * It may be worthwhile to mention that refs are part of the repository. * Is a ref a name? Or is it the binding of a name to an object/ref? I am not particularly interested in pedantry, but I think in the way we used the word ref, it is a name. refs/heads/master is the full name of the ref and it can be abbreviated to 'master' when not ambiguous. And there is a mechanism to read what the the ref has to learn the name of the object (*not* object/ref) it refers to (the name of that mechanism being ref resolution). To a layperson, a ref is one of the ways you can name an object with. -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/6] config doc: rewrite push.default section
Junio C Hamano gits...@pobox.com writes: or something like that. Just for a completeness, in a patch form: Documentation/config.txt | 66 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 81628e8..4b7fc54 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1833,37 +1833,49 @@ push.default:: `upstream` is probably what you want. Possible values are: + -- + * `nothing` - do not push anything (error out) unless a refspec is - explicitly given. Very safe, but not very convenient. + explicitly given. This is primarily meant for people who want to + avoid mistakes by always being explicit. * `current` - push the current branch to update a branch with the same name on the receiving end. Works in both central and non-central - workflows. Equivalent to pushing the refspec $branch ($branch is - the name of the current branch). - -* `upstream` - push the current branch to a branch with the name - branch.$branch.merge on the receiving end, and error out if the push - destination is not the same as branch.$branch.remote. The name - upstream refers to @{u[pstream]} in linkgit:gitrevisions[7], - which makes sense only if both branch.$branch.remote and - branch.$branch.merge are set. It makes sure that a `push` is - symmetrical to `pull` in central workflows, and cannot be used in - non-central workflows. - -* `simple` - a safer version of `current`; push the current branch to - update a branch with the same name on the receiving end, with a - safety feature: in central workflows, error out if - branch.$branch.merge is set and not equal to $branch, to make sure - that a `push` and `push` are never asymmetrical. It will become the - default in Git 2.0. - -* `matching` - push all branches having the same name on both ends - (essentially ignoring all newly created local branches). - Well-suited for those who want to batch-update a specific set of - branches they consistently work on. Use with caution, especially - when pushing with '--force'. Equivalent to pushing the refspec :. - This is currently the default, but Git 2.0 will change the default - to `simple`. + workflows. + +* `upstream` - push the current branch back to the branch whose + changes are usually integrated into the current branch (which is + called `@{upstream}`). This mode only makes sense if you are + pushing to the same repository you would normally pull from + (i.e. central workflow). + +* `simple` - a safer version of `current`; push the current branch + to update a branch with the same name on the receiving end, with a + safety feature: in central workflows, error out if your current + branch is not set to integrate with the branch with the same name, + to ensure that a `push` and a `push` are symmetrical. ++ +This mode will become the default in Git 2.0. + +* `matching` - push all branches having the same name on both ends. + This makes the repository you are pushing to remember the set of + branches that will be pushed out (e.g. if you always push 'maint' + and 'master' there and no other branches, the repository you push + to will have these two branches, and your local 'maint' and + 'master' will be pushed there). ++ +To use this mode effectively, you have to make sure _all_ the +branches you would push out are ready to be pushed out before +running 'git push', as the whole point of this mode is to allow you +to push all of the branches in one go. If you usually finish work +on only one branch and push out the result, while other branches are +unfinished, this mode is not for you. Also this mode is not +suitable for pushing into a shared central repository, as other +people may add new branches there, or update the tip of existing +branches outside your control. ++ +This is currently the default, but Git 2.0 will change the default +to `simple`. + -- rebase.stat:: -- 1.8.3.1-674-gb27e881 -- To unsubscribe from this list: send the line unsubscribe git in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html