-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* cc/replace: t6050: check pushing something based on a replaced commit Documentation: add documentation for "git replace" Add git-replace to .gitignore builtin-replace: use "usage_msg_opt" to give better error messages parse-options: add new function "usage_msg_opt" builtin-replace: teach "git replace" to actually replace Add new "git replace" command environment: add global variable to disable replacement mktag: call "check_sha1_signature" with the replacement sha1 replace_object: add a test case object: call "check_sha1_signature" with the replacement sha1 sha1_file: add a "read_sha1_file_repl" function replace_object: add mechanism to replace objects found in "refs/replace/" refs: add a "for_each_replace_ref" function
- Loading branch information
Showing
23 changed files
with
610 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
git-replace(1) | ||
============== | ||
|
||
NAME | ||
---- | ||
git-replace - Create, list, delete refs to replace objects | ||
|
||
SYNOPSIS | ||
-------- | ||
[verse] | ||
'git replace' [-f] <object> <replacement> | ||
'git replace' -d <object>... | ||
'git replace' -l [<pattern>] | ||
|
||
DESCRIPTION | ||
----------- | ||
Adds a 'replace' reference in `.git/refs/replace/` | ||
|
||
The name of the 'replace' reference is the SHA1 of the object that is | ||
replaced. The content of the replace reference is the SHA1 of the | ||
replacement object. | ||
|
||
Unless `-f` is given, the replace reference must not yet exist in | ||
`.git/refs/replace/` directory. | ||
|
||
OPTIONS | ||
------- | ||
-f:: | ||
If an existing replace ref for the same object exists, it will | ||
be overwritten (instead of failing). | ||
|
||
-d:: | ||
Delete existing replace refs for the given objects. | ||
|
||
-l <pattern>:: | ||
List replace refs for objects that match the given pattern (or | ||
all if no pattern is given). | ||
Typing "git replace" without arguments, also lists all replace | ||
refs. | ||
|
||
BUGS | ||
---- | ||
Comparing blobs or trees that have been replaced with those that | ||
replace them will not work properly. And using 'git reset --hard' to | ||
go back to a replaced commit will move the branch to the replacement | ||
commit instead of the replaced commit. | ||
|
||
There may be other problems when using 'git rev-list' related to | ||
pending objects. And of course things may break if an object of one | ||
type is replaced by an object of another type (for example a blob | ||
replaced by a commit). | ||
|
||
SEE ALSO | ||
-------- | ||
linkgit:git-tag[1] | ||
linkgit:git-branch[1] | ||
|
||
Author | ||
------ | ||
Written by Christian Couder <chriscool@tuxfamily.org> and Junio C | ||
Hamano <gitster@pobox.com>, based on 'git tag' by Kristian Hogsberg | ||
<krh@redhat.com> and Carlos Rica <jasampler@gmail.com>. | ||
|
||
Documentation | ||
-------------- | ||
Documentation by Christian Couder <chriscool@tuxfamily.org> and the | ||
git-list <git@vger.kernel.org>, based on 'git tag' documentation. | ||
|
||
GIT | ||
--- | ||
Part of the linkgit:git[1] suite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
/* | ||
* Builtin "git replace" | ||
* | ||
* Copyright (c) 2008 Christian Couder <chriscool@tuxfamily.org> | ||
* | ||
* Based on builtin-tag.c by Kristian Høgsberg <krh@redhat.com> | ||
* and Carlos Rica <jasampler@gmail.com> that was itself based on | ||
* git-tag.sh and mktag.c by Linus Torvalds. | ||
*/ | ||
|
||
#include "cache.h" | ||
#include "builtin.h" | ||
#include "refs.h" | ||
#include "parse-options.h" | ||
|
||
static const char * const git_replace_usage[] = { | ||
"git replace [-f] <object> <replacement>", | ||
"git replace -d <object>...", | ||
"git replace -l [<pattern>]", | ||
NULL | ||
}; | ||
|
||
static int show_reference(const char *refname, const unsigned char *sha1, | ||
int flag, void *cb_data) | ||
{ | ||
const char *pattern = cb_data; | ||
|
||
if (!fnmatch(pattern, refname, 0)) | ||
printf("%s\n", refname); | ||
|
||
return 0; | ||
} | ||
|
||
static int list_replace_refs(const char *pattern) | ||
{ | ||
if (pattern == NULL) | ||
pattern = "*"; | ||
|
||
for_each_replace_ref(show_reference, (void *) pattern); | ||
|
||
return 0; | ||
} | ||
|
||
typedef int (*each_replace_name_fn)(const char *name, const char *ref, | ||
const unsigned char *sha1); | ||
|
||
static int for_each_replace_name(const char **argv, each_replace_name_fn fn) | ||
{ | ||
const char **p; | ||
char ref[PATH_MAX]; | ||
int had_error = 0; | ||
unsigned char sha1[20]; | ||
|
||
for (p = argv; *p; p++) { | ||
if (snprintf(ref, sizeof(ref), "refs/replace/%s", *p) | ||
>= sizeof(ref)) { | ||
error("replace ref name too long: %.*s...", 50, *p); | ||
had_error = 1; | ||
continue; | ||
} | ||
if (!resolve_ref(ref, sha1, 1, NULL)) { | ||
error("replace ref '%s' not found.", *p); | ||
had_error = 1; | ||
continue; | ||
} | ||
if (fn(*p, ref, sha1)) | ||
had_error = 1; | ||
} | ||
return had_error; | ||
} | ||
|
||
static int delete_replace_ref(const char *name, const char *ref, | ||
const unsigned char *sha1) | ||
{ | ||
if (delete_ref(ref, sha1, 0)) | ||
return 1; | ||
printf("Deleted replace ref '%s'\n", name); | ||
return 0; | ||
} | ||
|
||
static int replace_object(const char *object_ref, const char *replace_ref, | ||
int force) | ||
{ | ||
unsigned char object[20], prev[20], repl[20]; | ||
char ref[PATH_MAX]; | ||
struct ref_lock *lock; | ||
|
||
if (get_sha1(object_ref, object)) | ||
die("Failed to resolve '%s' as a valid ref.", object_ref); | ||
if (get_sha1(replace_ref, repl)) | ||
die("Failed to resolve '%s' as a valid ref.", replace_ref); | ||
|
||
if (snprintf(ref, sizeof(ref), | ||
"refs/replace/%s", | ||
sha1_to_hex(object)) > sizeof(ref) - 1) | ||
die("replace ref name too long: %.*s...", 50, ref); | ||
if (check_ref_format(ref)) | ||
die("'%s' is not a valid ref name.", ref); | ||
|
||
if (!resolve_ref(ref, prev, 1, NULL)) | ||
hashclr(prev); | ||
else if (!force) | ||
die("replace ref '%s' already exists", ref); | ||
|
||
lock = lock_any_ref_for_update(ref, prev, 0); | ||
if (!lock) | ||
die("%s: cannot lock the ref", ref); | ||
if (write_ref_sha1(lock, repl, NULL) < 0) | ||
die("%s: cannot update the ref", ref); | ||
|
||
return 0; | ||
} | ||
|
||
int cmd_replace(int argc, const char **argv, const char *prefix) | ||
{ | ||
int list = 0, delete = 0, force = 0; | ||
struct option options[] = { | ||
OPT_BOOLEAN('l', NULL, &list, "list replace refs"), | ||
OPT_BOOLEAN('d', NULL, &delete, "delete replace refs"), | ||
OPT_BOOLEAN('f', NULL, &force, "replace the ref if it exists"), | ||
OPT_END() | ||
}; | ||
|
||
argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0); | ||
|
||
if (list && delete) | ||
usage_msg_opt("-l and -d cannot be used together", | ||
git_replace_usage, options); | ||
|
||
if (force && (list || delete)) | ||
usage_msg_opt("-f cannot be used with -d or -l", | ||
git_replace_usage, options); | ||
|
||
/* Delete refs */ | ||
if (delete) { | ||
if (argc < 1) | ||
usage_msg_opt("-d needs at least one argument", | ||
git_replace_usage, options); | ||
return for_each_replace_name(argv, delete_replace_ref); | ||
} | ||
|
||
/* Replace object */ | ||
if (!list && argc) { | ||
if (argc != 2) | ||
usage_msg_opt("bad number of arguments", | ||
git_replace_usage, options); | ||
return replace_object(argv[0], argv[1], force); | ||
} | ||
|
||
/* List refs, even if "list" is not set */ | ||
if (argc > 1) | ||
usage_msg_opt("only one pattern can be given with -l", | ||
git_replace_usage, options); | ||
if (force) | ||
usage_msg_opt("-f needs some arguments", | ||
git_replace_usage, options); | ||
|
||
return list_replace_refs(argv[0]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.