git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [BUG] Cannot push some grafted branches

From
Jeff King <peff@peff.net>
Date
Dec 18, 2012, 16:24 UTC
Message-ID
<20121218162402.GA20122@sigill.intra.peff.net>
In-Reply-To
<20121218144157.00ccd915@chalon.bertin.fr>
On Tue, Dec 18, 2012 at 02:41:57PM +0100, Yann Dirson wrote:
Show 6 quoted lines
> > I wouldn't even want a script -- we'd end up inventing a complicated
> > command-line editor for what can simply be done by judicious use of an
> > actual text editor.  How about something like the following?
> 
> Well, while it does the job, it is still hardly as straightforward as the
> old "vi .git/info/grafts", or as a single easily-remembered commandline.

I wouldn't discount coming up with something based around "git commit" that might be easier to use for specific instances, but it does seem like an obvious feature to "git replace" to encapsulate Thomas's edit script, which is the most general form.

I am not really interested in pushing this forward myself, but I worked up this toy that somebody might find interesting (you can "git replace HEAD~20" to get dumped in an editor). It should probably handle trees, and it would probably make sense to do per-object-type sanity checks (e.g., call verify_tag on tags).

diff --git a/builtin/replace.c b/builtin/replace.c
index 398ccd5..90979b6 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -81,6 +81,57 @@ static int delete_replace_ref(const char *name, const char *ref,
 	return 0;
 }
 
+static void edit_buffer(struct strbuf *out, const char *buf, unsigned long len)
+{
+	char tmpfile[PATH_MAX];
+	int fd;
+
+	fd = git_mkstemp(tmpfile, sizeof(tmpfile), "replace.XXXXXX");
+	if (fd < 0)
+		die_errno("unable to create tempfile");
+	if (write_in_full(fd, buf, len) < 0)
+		die_errno("unable to write to tempfile");
+	if (launch_editor(tmpfile, out, NULL) < 0)
+		die_errno("unable to run editor");
+
+	close(fd);
+	unlink_or_warn(tmpfile);
+}
+
+static void edit_object(unsigned char old[20], unsigned char new[20])
+{
+	enum object_type type;
+	unsigned long size;
+	char *old_buf;
+	struct strbuf new_buf = STRBUF_INIT;
+
+	old_buf = read_sha1_file_extended(old, &type, &size, 0);
+	if (!old_buf)
+		die("unable to read object '%s'", sha1_to_hex(old));
+
+	switch (type) {
+	case OBJ_COMMIT:
+	case OBJ_TAG:
+	case OBJ_BLOB:
+		/* These are OK to edit literally. */
+		edit_buffer(&new_buf, old_buf, size);
+		break;
+	case OBJ_TREE:
+		/*
+		 * XXX we'd probably want to massage this into ls-tree format,
+		 * and then read the result back via mktree.
+		 */
+		die("editing tree objects is not yet supported");
+	default:
+		die("unknown object type for %s", sha1_to_hex(old));
+	}
+
+	if (write_sha1_file(new_buf.buf, new_buf.len, typename(type), new) < 0)
+		die("unable to write replacement object");
+	free(old_buf);
+	strbuf_release(&new_buf);
+}
+
 static int replace_object(const char *object_ref, const char *replace_ref,
 			  int force)
 {
@@ -90,7 +141,7 @@ static int replace_object(const char *object_ref, const char *replace_ref,
 
 	if (get_sha1(object_ref, object))
 		die("Failed to resolve '%s' as a valid ref.", object_ref);
-	if (get_sha1(replace_ref, repl))
+	if (replace_ref && get_sha1(replace_ref, repl))
 		die("Failed to resolve '%s' as a valid ref.", replace_ref);
 
 	if (snprintf(ref, sizeof(ref),
@@ -105,6 +156,9 @@ static int replace_object(const char *object_ref, const char *replace_ref,
 	else if (!force)
 		die("replace ref '%s' already exists", ref);
 
+	if (!replace_ref)
+		edit_object(object, repl);
+
 	lock = lock_any_ref_for_update(ref, prev, 0);
 	if (!lock)
 		die("%s: cannot lock the ref", ref);
@@ -144,7 +198,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
 
 	/* Replace object */
 	if (!list && argc) {
-		if (argc != 2)
+		if (argc < 1 || argc > 2)
 			usage_msg_opt("bad number of arguments",
 				      git_replace_usage, options);
 		return replace_object(argv[0], argv[1], force);
Previous: Thomas RastNext: Johannes Sixt
Message 20 of 29 in “[BUG] Cannot push some grafted branches”
  1. Yann DirsonDec 11, 2012
  2. Junio C HamanoDec 11, 2012
  3. Yann DirsonDec 12, 2012
  4. Yann DirsonDec 12, 2012
  5. Junio C HamanoDec 12, 2012
  6. Yann DirsonDec 17, 2012
  7. Junio C HamanoDec 17, 2012
  8. Yann DirsonDec 17, 2012
  9. Thomas RastDec 17, 2012
  10. Yann DirsonDec 17, 2012
  11. Christian CouderDec 17, 2012
  12. Yann DirsonDec 17, 2012
  13. Andreas SchwabDec 17, 2012
  14. Junio C HamanoDec 17, 2012
  15. Yann DirsonDec 18, 2012
  16. Johannes SixtDec 18, 2012
  17. Thomas RastDec 18, 2012
  18. Yann DirsonDec 18, 2012
  19. Thomas RastDec 18, 2012
  20. Jeff KingDec 18, 2012
  21. Johannes SixtDec 19, 2012
  22. Jeff KingDec 19, 2012
  23. Junio C HamanoDec 18, 2012
  24. Yann DirsonDec 19, 2012
  25. Thomas RastDec 19, 2012
  26. Junio C HamanoDec 19, 2012
  27. Michael J GruberDec 21, 2012
  28. Junio C HamanoDec 21, 2012
  29. Michael J GruberDec 22, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.