Re: [PATCH v6 6/7] git-reflog: add create and exists functions

2015-07-08 Thread Michael Haggerty
On 07/08/2015 02:49 AM, David Turner wrote:
 On Mon, 2015-07-06 at 18:51 +0200, Michael Haggerty wrote:
 [...]
 So all in all, I think it is unwise to allow a reflog to be created
 without its corresponding reference.

 This, in turn, suggests one or both of the following alternatives:

 1. Allow git reflog create, but only for references that already exist.
 
 This turns out not to work for git stash, which wants to create a reflog
 for stash creation.
 
 2. If we want to allow a reflog to be created at the same time as the
 corresponding reference, the reference-creation commands (git branch,
 git tag, git update-ref, and maybe some others) probably need a new
 option like --create-reflog (and, for symmetry, probably
 --no-create-reflog).
 
 git branch should already autocreate reflogs, since the refs it creates
 are under refs/heads.

`git branch` only autocreates reflogs if core.logAllRefUpdates is on.
That setting happens to be on by default in a non-bare repository but
the user might turn it off. And it is off by default in a bare repository.

In my opinion it would be nice for the user to be able to ask for a
reflog to be created for a branch regardless of how
core.logAllRefUpdates is set. Though I'm not saying that you have to be
the one to implement that functionality :-)

 At the API level, it might make sense for the ref-transaction functions
 to get a new REF_FORCE_CREATE_REFLOG flag or something.
 
 Junio was opposed to the converse flag, so I'm going to just add
 manually add code to create reflogs.

Unfortunately I wasn't keeping up with earlier versions of this patch
series and now I can't find the email from Junio that you are referring
to. If the earlier flag had the opposite (converse?) sense, like
REF_INHIBIT_CREATE_REFLOG, then I agree that it wouldn't be an improvement.

But I think this functionality *has to* be implemented within ref
transactions for references that are just being created, because

1. The reflog must *not* be created if the reference creation fails for
some reason. For example, the reflog shouldn't be created if the
reference name has a D/F conflict with an existing one in the refs/foo
vs. refs/foo/bar sense. (This conflict might not be obvious when
creating the reflog file because the other reference might not have its
reflog turned on.) There are other reasons that a reference creation
might fail, and code outside of the refs API can't be expected to know
all possibilities.

2. On the other hand, the reflog for a newly-created reference *should*
reflect the creation of the reference. So it would be awkward to require
the calling code to create the reference and *then* turn on the reflog.

For references that already exist, I see no problem with a command that
turns on the reflog without adding any entries to it. Though if you
implement this, it would be prudent to check that existing
reflog-handling code doesn't fail when confronted with an empty file; I
think empty reflog files are rare now and might not be well-tested.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu

--
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 v6 6/7] git-reflog: add create and exists functions

2015-07-08 Thread David Turner
On Wed, 2015-07-08 at 15:16 +0200, Michael Haggerty wrote:
 On 07/08/2015 02:49 AM, David Turner wrote:
  On Mon, 2015-07-06 at 18:51 +0200, Michael Haggerty wrote:
  [...]
  So all in all, I think it is unwise to allow a reflog to be created
  without its corresponding reference.
 
  This, in turn, suggests one or both of the following alternatives:
 
  1. Allow git reflog create, but only for references that already exist.
  
  This turns out not to work for git stash, which wants to create a reflog
  for stash creation.
  
  2. If we want to allow a reflog to be created at the same time as the
  corresponding reference, the reference-creation commands (git branch,
  git tag, git update-ref, and maybe some others) probably need a new
  option like --create-reflog (and, for symmetry, probably
  --no-create-reflog).
  
  git branch should already autocreate reflogs, since the refs it creates
  are under refs/heads.
 
 `git branch` only autocreates reflogs if core.logAllRefUpdates is on.
 That setting happens to be on by default in a non-bare repository but
 the user might turn it off. And it is off by default in a bare repository.

Oh, right.  Well, we can always add that later, if anyone needs it.

 In my opinion it would be nice for the user to be able to ask for a
 reflog to be created for a branch regardless of how
 core.logAllRefUpdates is set. Though I'm not saying that you have to be
 the one to implement that functionality :-)
 
  At the API level, it might make sense for the ref-transaction functions
  to get a new REF_FORCE_CREATE_REFLOG flag or something.
  
  Junio was opposed to the converse flag, so I'm going to just add
  manually add code to create reflogs.
 
 Unfortunately I wasn't keeping up with earlier versions of this patch
 series and now I can't find the email from Junio that you are referring
 to. If the earlier flag had the opposite (converse?) sense, like
 REF_INHIBIT_CREATE_REFLOG, then I agree that it wouldn't be an improvement.
 
 But I think this functionality *has to* be implemented within ref
 transactions for references that are just being created, because
 
 1. The reflog must *not* be created if the reference creation fails for
 some reason. For example, the reflog shouldn't be created if the
 reference name has a D/F conflict with an existing one in the refs/foo
 vs. refs/foo/bar sense. (This conflict might not be obvious when
 creating the reflog file because the other reference might not have its
 reflog turned on.) There are other reasons that a reference creation
 might fail, and code outside of the refs API can't be expected to know
 all possibilities.
 
 2. On the other hand, the reflog for a newly-created reference *should*
 reflect the creation of the reference. So it would be awkward to require
 the calling code to create the reference and *then* turn on the reflog.

Yep, makes sense.

 For references that already exist, I see no problem with a command that
 turns on the reflog without adding any entries to it. Though if you
 implement this, it would be prudent to check that existing
 reflog-handling code doesn't fail when confronted with an empty file; I
 think empty reflog files are rare now and might not be well-tested.

I think empty reflog files are fine; I recall a few tests creating them
(and git stash did so as well).

But I also don't need that command (I think), so I won't implement it
right now.

--
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 v6 6/7] git-reflog: add create and exists functions

2015-07-07 Thread David Turner
On Mon, 2015-07-06 at 18:51 +0200, Michael Haggerty wrote:

  +{
  +   int i, status = 0, start = 0;
 
 It looks like start is initialized unconditionally after the first loop,
 so the initialization here is a red herring.

Will fix.

 So, I have a philosophical question here with a practical side...
 
 It appears that this command allows you to create a reflog for a
 reference that doesn't yet exist. At first blush, this seems to make
 sense. Suppose you want the creation of a reference to be logged. Then
 you can first turn on its reflog, then create it.
 
 But I think this is going to create problems. Reflogs are rather
 intimately connected to their references. For example, writes to a
 reflog are guarded by locking the corresponding reference. And currently
 a reflog file is deleted when the corresponding reference is deleted.
 Also, there are constraints about which references can coexist; for
 example, references refs/heads/foo and refs/heads/foo/bar cannot
 exist at the same time, because (at least when using the filesystem
 backend), refs/heads/foo would have to be both a file and a directory
 at the same time. So if one of these references already exists, it would
 be an error to create a reflog for the other one.
 
 Similarly, if there is a reflog file for one of these references that
 was created by this command, but there is not yet a corresponding
 reference, then any command that later tries to create the other
 reference will not be able to create the reflog for *that* reference
 because it will conflict with the existing reflog. I doubt that the
 reference creation is smart enough to deal with this situation.
 
 So all in all, I think it is unwise to allow a reflog to be created
 without its corresponding reference.
 
 This, in turn, suggests one or both of the following alternatives:
 
 1. Allow git reflog create, but only for references that already exist.

This turns out not to work for git stash, which wants to create a reflog
for stash creation.

 2. If we want to allow a reflog to be created at the same time as the
 corresponding reference, the reference-creation commands (git branch,
 git tag, git update-ref, and maybe some others) probably need a new
 option like --create-reflog (and, for symmetry, probably
 --no-create-reflog).

git branch should already autocreate reflogs, since the refs it creates
are under refs/heads.

 At the API level, it might make sense for the ref-transaction functions
 to get a new REF_FORCE_CREATE_REFLOG flag or something.

Junio was opposed to the converse flag, so I'm going to just add
manually add code to create reflogs.


--
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 v6 6/7] git-reflog: add create and exists functions

2015-07-06 Thread Michael Haggerty
On 06/29/2015 10:17 PM, David Turner wrote:
 These are necessary because alternate ref backends might store reflogs
 somewhere other than .git/logs.  Code that now directly manipulates
 .git/logs should instead go through git-reflog.
 
 In a moment, we will use these functions to make git stash work with
 alternate ref backends.
 
 Signed-off-by: David Turner dtur...@twopensource.com
 ---
  Documentation/git-reflog.txt | 10 ++
  builtin/reflog.c | 75 
 +++-
  t/t1411-reflog-show.sh   | 12 +++
  3 files changed, 96 insertions(+), 1 deletion(-)
 
 diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
 index 5e7908e..2bf8aa6 100644
 --- a/Documentation/git-reflog.txt
 +++ b/Documentation/git-reflog.txt
 @@ -23,6 +23,8 @@ depending on the subcommand:
   [--dry-run] [--verbose] [--all | refs...]
  'git reflog delete' [--rewrite] [--updateref]
   [--dry-run] [--verbose] ref@\{specifier\}...
 +'git reflog create' refs...
 +'git reflog exists' ref
  
  Reference logs, or reflogs, record when the tips of branches and
  other references were updated in the local repository. Reflogs are
 @@ -52,6 +54,14 @@ argument must be an _exact_ entry (e.g. `git reflog delete
  master@{2}`). This subcommand is also typically not used directly by
  end users.
  
 +The create subcommand creates a reflog for one or more refs. Most
 +refs (those under refs/heads, refs/remotes, and refs/tags) will
 +automatically have reflogs created. Other refs will not. This command
 +allows manual ref creation.
 +
 +The exists subcommand checks whether a ref has a reflog.  It exists
 +with zero status if the reflog exists, and non-zero status if it does
 +not.
  
  OPTIONS
  ---
 diff --git a/builtin/reflog.c b/builtin/reflog.c
 index c2eb8ff..3080865 100644
 --- a/builtin/reflog.c
 +++ b/builtin/reflog.c
 @@ -13,6 +13,10 @@ static const char reflog_expire_usage[] =
  git reflog expire [--expire=time] [--expire-unreachable=time] 
 [--rewrite] [--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] 
 refs...;
  static const char reflog_delete_usage[] =
  git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] 
 refs...;
 +static const char reflog_create_usage[] =
 +git reflog create refs...;
 +static const char reflog_exists_usage[] =
 +git reflog exists ref;
  
  static unsigned long default_reflog_expire;
  static unsigned long default_reflog_expire_unreachable;
 @@ -699,12 +703,75 @@ static int cmd_reflog_delete(int argc, const char 
 **argv, const char *prefix)
   return status;
  }
  
 +static int cmd_reflog_create(int argc, const char **argv, const char *prefix)
 +{
 + int i, status = 0, start = 0;

It looks like start is initialized unconditionally after the first loop,
so the initialization here is a red herring.

 + struct strbuf err = STRBUF_INIT;
 +
 + for (i = 1; i  argc; i++) {
 + const char *arg = argv[i];
 + if (!strcmp(arg, --)) {
 + i++;
 + break;
 + }
 + else if (arg[0] == '-')
 + usage(reflog_create_usage);
 + else
 + break;
 + }
 +
 + start = i;
 +
 + if (argc - start  1)

if (start == argc)

seems clearer, but that might just be me.

 + return error(Nothing to create?);
 +
 + for (i = start; i  argc; i++) {
 + if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL))
 + die(invalid ref format: %s, argv[i]);
 + }
 + for (i = start; i  argc; i++) {
 + if (safe_create_reflog(argv[i], err, 1)) {
 + error(could not create reflog %s: %s, argv[i],
 +   err.buf);
 + status = 1;
 + strbuf_release(err);
 + }
 + }
 + return status;
 +}
 +

So, I have a philosophical question here with a practical side...

It appears that this command allows you to create a reflog for a
reference that doesn't yet exist. At first blush, this seems to make
sense. Suppose you want the creation of a reference to be logged. Then
you can first turn on its reflog, then create it.

But I think this is going to create problems. Reflogs are rather
intimately connected to their references. For example, writes to a
reflog are guarded by locking the corresponding reference. And currently
a reflog file is deleted when the corresponding reference is deleted.
Also, there are constraints about which references can coexist; for
example, references refs/heads/foo and refs/heads/foo/bar cannot
exist at the same time, because (at least when using the filesystem
backend), refs/heads/foo would have to be both a file and a directory
at the same time. So if one of these references already exists, it would
be an error to create a reflog for the other one.

Similarly, if there is a reflog file for one of these references 

Re: [PATCH v6 6/7] git-reflog: add create and exists functions

2015-06-30 Thread Eric Sunshine
On Mon, Jun 29, 2015 at 4:17 PM, David Turner dtur...@twopensource.com wrote:
 These are necessary because alternate ref backends might store reflogs
 somewhere other than .git/logs.  Code that now directly manipulates
 .git/logs should instead go through git-reflog.

 In a moment, we will use these functions to make git stash work with
 alternate ref backends.

 Signed-off-by: David Turner dtur...@twopensource.com
 ---
 diff --git a/builtin/reflog.c b/builtin/reflog.c
 index c2eb8ff..3080865 100644
 --- a/builtin/reflog.c
 +++ b/builtin/reflog.c
 @@ -13,6 +13,10 @@ static const char reflog_expire_usage[] =
 +static int cmd_reflog_create(int argc, const char **argv, const char *prefix)
 +{
 +   int i, status = 0, start = 0;
 +   struct strbuf err = STRBUF_INIT;
 +
 +   for (i = 1; i  argc; i++) {
 +   const char *arg = argv[i];
 +   if (!strcmp(arg, --)) {
 +   i++;
 +   break;
 +   }
 +   else if (arg[0] == '-')
 +   usage(reflog_create_usage);
 +   else
 +   break;
 +   }
 +
 +   start = i;
 +
 +   if (argc - start  1)
 +   return error(Nothing to create?);
 +
 +   for (i = start; i  argc; i++) {
 +   if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL))
 +   die(invalid ref format: %s, argv[i]);
 +   }
 +   for (i = start; i  argc; i++) {
 +   if (safe_create_reflog(argv[i], err, 1)) {
 +   error(could not create reflog %s: %s, argv[i],
 + err.buf);
 +   status = 1;
 +   strbuf_release(err);

This feels a bit dirty. While it's true that the current
implementation of strbuf_release() re-initializes the strbuf (so
you're not technically wrong by re-using it), that's an implementation
detail; and indeed, the strbuf_release() documentation says:

Release a string buffer and the memory it used. You should not
use the string buffer after using this function, unless you
initialize it again.

Alternatives would be strbuf_reset() or declaring and releasing the
strbuf within the for-loop scope.

 +   }
 +   }
 +   return status;
 +}
--
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 v6 6/7] git-reflog: add create and exists functions

2015-06-30 Thread David Turner
On Tue, 2015-06-30 at 03:34 -0400, Eric Sunshine wrote:
  +   strbuf_release(err);
 
 This feels a bit dirty. While it's true that the current

Thanks.  New patchset pushed to the branch on github:

https://github.com/dturner-tw/git.git
dturner/pluggable-backends-preamble



--
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 v6 6/7] git-reflog: add create and exists functions

2015-06-30 Thread Junio C Hamano
Eric Sunshine sunsh...@sunshineco.com writes:

 +   for (i = start; i  argc; i++) {
 +   if (safe_create_reflog(argv[i], err, 1)) {
 +   error(could not create reflog %s: %s, argv[i],
 + err.buf);
 +   status = 1;
 +   strbuf_release(err);

 This feels a bit dirty.

Hmm, I do not share that feeling.  I wouldn't be surprised if you
found a lot of existing codepaths that run _init() a strbuf once,
work on it and then _release() once a section of code is done with
it, reuse it for further (unrelated) processing, knowing that
_release() implicitly did _init() and the strbuf is ready to use
after that.  I thought that was a very well established pattern.

 While it's true that the current
 implementation of strbuf_release() re-initializes the strbuf (so
 you're not technically wrong by re-using it), that's an implementation
 detail; and indeed, the strbuf_release() documentation says:

 Release a string buffer and the memory it used. You should not
 use the string buffer after using this function, unless you
 initialize it again.

Hmph. Perhaps the doc is wrong? ;-)

 Alternatives would be strbuf_reset() or declaring and releasing the
 strbuf within the for-loop scope.

Because _reset() just rewinds the .len pointer without deallocating,
you would need an extra _release() before it goes out of scope. If
it is expected that the strbuf will be reused for a number of times,
the length of the string each iteration uses is similar, and you
will iterate the loop many times, _reset() each time and _release()
to clean-up pattern would save many calls to realloc/free.
--
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 v6 6/7] git-reflog: add create and exists functions

2015-06-30 Thread Eric Sunshine
On Tue, Jun 30, 2015 at 12:07 PM, Junio C Hamano gits...@pobox.com wrote:
 Eric Sunshine sunsh...@sunshineco.com writes:

 +   for (i = start; i  argc; i++) {
 +   if (safe_create_reflog(argv[i], err, 1)) {
 +   error(could not create reflog %s: %s, argv[i],
 + err.buf);
 +   status = 1;
 +   strbuf_release(err);

 This feels a bit dirty.

 Hmm, I do not share that feeling.  I wouldn't be surprised if you
 found a lot of existing codepaths that run _init() a strbuf once,
 work on it and then _release() once a section of code is done with
 it, reuse it for further (unrelated) processing, knowing that
 _release() implicitly did _init() and the strbuf is ready to use
 after that.  I thought that was a very well established pattern.

That could the case, and I may not be familiar with code doing that.

I have, however, seen plenty of code which uses strbuf_reset() in the
way you describe.

 While it's true that the current
 implementation of strbuf_release() re-initializes the strbuf (so
 you're not technically wrong by re-using it), that's an implementation
 detail; and indeed, the strbuf_release() documentation says:

 Release a string buffer and the memory it used. You should not
 use the string buffer after using this function, unless you
 initialize it again.

 Hmph. Perhaps the doc is wrong? ;-)

Perhaps. I always interpreted the documentation as meaning that the
project reserved the right to change the underlying implementation.

 Alternatives would be strbuf_reset() or declaring and releasing the
 strbuf within the for-loop scope.

 Because _reset() just rewinds the .len pointer without deallocating,
 you would need an extra _release() before it goes out of scope. If
 it is expected that the strbuf will be reused for a number of times,
 the length of the string each iteration uses is similar, and you
 will iterate the loop many times, _reset() each time and _release()
 to clean-up pattern would save many calls to realloc/free.

Yep, that's why I suggested strbuf_reset() as an alternative (and
likely would have chosen it myself).
--
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 v6 6/7] git-reflog: add create and exists functions

2015-06-30 Thread Junio C Hamano
Eric Sunshine sunsh...@sunshineco.com writes:

 Alternatives would be strbuf_reset() or declaring and releasing the
 strbuf within the for-loop scope.

 Because _reset() just rewinds the .len pointer without deallocating,
 you would need an extra _release() before it goes out of scope. If
 it is expected that the strbuf will be reused for a number of times,
 the length of the string each iteration uses is similar, and you
 will iterate the loop many times, _reset() each time and _release()
 to clean-up pattern would save many calls to realloc/free.

 Yep, that's why I suggested strbuf_reset() as an alternative (and
 likely would have chosen it myself).

OK, then let's do that by squashing this in.

 builtin/reflog.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/builtin/reflog.c b/builtin/reflog.c
index 3080865..e9ba600 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -733,10 +733,11 @@ static int cmd_reflog_create(int argc, const char **argv, 
const char *prefix)
if (safe_create_reflog(argv[i], err, 1)) {
error(could not create reflog %s: %s, argv[i],
  err.buf);
+   strbuf_reset(err);
status = 1;
-   strbuf_release(err);
}
}
+   strbuf_release(err);
return status;
 }
 
--
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 v6 6/7] git-reflog: add create and exists functions

2015-06-30 Thread David Turner
On Tue, 2015-06-30 at 12:48 -0700, Junio C Hamano wrote:
 Eric Sunshine sunsh...@sunshineco.com writes:
 
  Alternatives would be strbuf_reset() or declaring and releasing the
  strbuf within the for-loop scope.
 
  Because _reset() just rewinds the .len pointer without deallocating,
  you would need an extra _release() before it goes out of scope. If
  it is expected that the strbuf will be reused for a number of times,
  the length of the string each iteration uses is similar, and you
  will iterate the loop many times, _reset() each time and _release()
  to clean-up pattern would save many calls to realloc/free.
 
  Yep, that's why I suggested strbuf_reset() as an alternative (and
  likely would have chosen it myself).
 
 OK, then let's do that by squashing this in.
 
  builtin/reflog.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

I squashed that into my repo on github:

https://github.com/dturner-tw/git.git
on the branch dturner/pluggable-backends-preamble

--
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 v6 6/7] git-reflog: add create and exists functions

2015-06-30 Thread Junio C Hamano
David Turner dtur...@twopensource.com writes:

 On Tue, 2015-06-30 at 12:48 -0700, Junio C Hamano wrote:
 Eric Sunshine sunsh...@sunshineco.com writes:
 
  Alternatives would be strbuf_reset() or declaring and releasing the
  strbuf within the for-loop scope.
 
  Because _reset() just rewinds the .len pointer without deallocating,
  you would need an extra _release() before it goes out of scope. If
  it is expected that the strbuf will be reused for a number of times,
  the length of the string each iteration uses is similar, and you
  will iterate the loop many times, _reset() each time and _release()
  to clean-up pattern would save many calls to realloc/free.
 
  Yep, that's why I suggested strbuf_reset() as an alternative (and
  likely would have chosen it myself).
 
 OK, then let's do that by squashing this in.
 
  builtin/reflog.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

 I squashed that into my repo on github:

I'm already deep into today's integration cycle, so it is unlikely
I'd pull that before I push the result out.  Please let me know if
the resulting tree looks wrong (I only queued it to be squashed,
haven't done the squashing two into one yet).

Thanks.  The 7-patch series with this fixup looks good to me.
--
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 v6 6/7] git-reflog: add create and exists functions

2015-06-29 Thread David Turner
These are necessary because alternate ref backends might store reflogs
somewhere other than .git/logs.  Code that now directly manipulates
.git/logs should instead go through git-reflog.

In a moment, we will use these functions to make git stash work with
alternate ref backends.

Signed-off-by: David Turner dtur...@twopensource.com
---
 Documentation/git-reflog.txt | 10 ++
 builtin/reflog.c | 75 +++-
 t/t1411-reflog-show.sh   | 12 +++
 3 files changed, 96 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
index 5e7908e..2bf8aa6 100644
--- a/Documentation/git-reflog.txt
+++ b/Documentation/git-reflog.txt
@@ -23,6 +23,8 @@ depending on the subcommand:
[--dry-run] [--verbose] [--all | refs...]
 'git reflog delete' [--rewrite] [--updateref]
[--dry-run] [--verbose] ref@\{specifier\}...
+'git reflog create' refs...
+'git reflog exists' ref
 
 Reference logs, or reflogs, record when the tips of branches and
 other references were updated in the local repository. Reflogs are
@@ -52,6 +54,14 @@ argument must be an _exact_ entry (e.g. `git reflog delete
 master@{2}`). This subcommand is also typically not used directly by
 end users.
 
+The create subcommand creates a reflog for one or more refs. Most
+refs (those under refs/heads, refs/remotes, and refs/tags) will
+automatically have reflogs created. Other refs will not. This command
+allows manual ref creation.
+
+The exists subcommand checks whether a ref has a reflog.  It exists
+with zero status if the reflog exists, and non-zero status if it does
+not.
 
 OPTIONS
 ---
diff --git a/builtin/reflog.c b/builtin/reflog.c
index c2eb8ff..3080865 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -13,6 +13,10 @@ static const char reflog_expire_usage[] =
 git reflog expire [--expire=time] [--expire-unreachable=time] [--rewrite] 
[--updateref] [--stale-fix] [--dry-run | -n] [--verbose] [--all] refs...;
 static const char reflog_delete_usage[] =
 git reflog delete [--rewrite] [--updateref] [--dry-run | -n] [--verbose] 
refs...;
+static const char reflog_create_usage[] =
+git reflog create refs...;
+static const char reflog_exists_usage[] =
+git reflog exists ref;
 
 static unsigned long default_reflog_expire;
 static unsigned long default_reflog_expire_unreachable;
@@ -699,12 +703,75 @@ static int cmd_reflog_delete(int argc, const char **argv, 
const char *prefix)
return status;
 }
 
+static int cmd_reflog_create(int argc, const char **argv, const char *prefix)
+{
+   int i, status = 0, start = 0;
+   struct strbuf err = STRBUF_INIT;
+
+   for (i = 1; i  argc; i++) {
+   const char *arg = argv[i];
+   if (!strcmp(arg, --)) {
+   i++;
+   break;
+   }
+   else if (arg[0] == '-')
+   usage(reflog_create_usage);
+   else
+   break;
+   }
+
+   start = i;
+
+   if (argc - start  1)
+   return error(Nothing to create?);
+
+   for (i = start; i  argc; i++) {
+   if (check_refname_format(argv[i], REFNAME_ALLOW_ONELEVEL))
+   die(invalid ref format: %s, argv[i]);
+   }
+   for (i = start; i  argc; i++) {
+   if (safe_create_reflog(argv[i], err, 1)) {
+   error(could not create reflog %s: %s, argv[i],
+ err.buf);
+   status = 1;
+   strbuf_release(err);
+   }
+   }
+   return status;
+}
+
+static int cmd_reflog_exists(int argc, const char **argv, const char *prefix)
+{
+   int i, start = 0;
+
+   for (i = 1; i  argc; i++) {
+   const char *arg = argv[i];
+   if (!strcmp(arg, --)) {
+   i++;
+   break;
+   }
+   else if (arg[0] == '-')
+   usage(reflog_exists_usage);
+   else
+   break;
+   }
+
+   start = i;
+
+   if (argc - start != 1)
+   usage(reflog_exists_usage);
+
+   if (check_refname_format(argv[start], REFNAME_ALLOW_ONELEVEL))
+   die(invalid ref format: %s, argv[start]);
+   return !reflog_exists(argv[start]);
+}
+
 /*
  * main reflog
  */
 
 static const char reflog_usage[] =
-git reflog [ show | expire | delete ];
+git reflog [ show | expire | delete | create | exists ];
 
 int cmd_reflog(int argc, const char **argv, const char *prefix)
 {
@@ -724,5 +791,11 @@ int cmd_reflog(int argc, const char **argv, const char 
*prefix)
if (!strcmp(argv[1], delete))
return cmd_reflog_delete(argc - 1, argv + 1, prefix);
 
+   if (!strcmp(argv[1], create))
+   return cmd_reflog_create(argc - 1, argv + 1, prefix);
+
+   if (!strcmp(argv[1], exists))
+