forked from gitster/git
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* db/checkout: (21 commits) checkout: error out when index is unmerged even with -m checkout: show progress when checkout takes long time while switching branches Add merge-subtree back checkout: updates to tracking report builtin-checkout.c: Remove unused prefix arguments in switch_branches path checkout: work from a subdirectory checkout: tone down the "forked status" diagnostic messages Clean up reporting differences on branch switch builtin-checkout.c: fix possible usage segfault checkout: notice when the switched branch is behind or forked Build in checkout Move code to clean up after a branch change to branch.c Library function to check for unmerged index entries Use diff -u instead of diff in t7201 Move create_branch into a library file Build-in merge-recursive Add "skip_unmerged" option to unpack_trees. Discard "deleted" cache entries after using them to update the working tree Send unpack-trees debugging output to stderr Add flag to make unpack_trees() not print errors. ... Conflicts: Makefile
- Loading branch information
Showing
20 changed files
with
1,002 additions
and
271 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,148 @@ | ||
#include "cache.h" | ||
#include "branch.h" | ||
#include "refs.h" | ||
#include "remote.h" | ||
#include "commit.h" | ||
|
||
struct tracking { | ||
struct refspec spec; | ||
char *src; | ||
const char *remote; | ||
int matches; | ||
}; | ||
|
||
static int find_tracked_branch(struct remote *remote, void *priv) | ||
{ | ||
struct tracking *tracking = priv; | ||
|
||
if (!remote_find_tracking(remote, &tracking->spec)) { | ||
if (++tracking->matches == 1) { | ||
tracking->src = tracking->spec.src; | ||
tracking->remote = remote->name; | ||
} else { | ||
free(tracking->spec.src); | ||
if (tracking->src) { | ||
free(tracking->src); | ||
tracking->src = NULL; | ||
} | ||
} | ||
tracking->spec.src = NULL; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* This is called when new_ref is branched off of orig_ref, and tries | ||
* to infer the settings for branch.<new_ref>.{remote,merge} from the | ||
* config. | ||
*/ | ||
static int setup_tracking(const char *new_ref, const char *orig_ref) | ||
{ | ||
char key[1024]; | ||
struct tracking tracking; | ||
|
||
if (strlen(new_ref) > 1024 - 7 - 7 - 1) | ||
return error("Tracking not set up: name too long: %s", | ||
new_ref); | ||
|
||
memset(&tracking, 0, sizeof(tracking)); | ||
tracking.spec.dst = (char *)orig_ref; | ||
if (for_each_remote(find_tracked_branch, &tracking) || | ||
!tracking.matches) | ||
return 1; | ||
|
||
if (tracking.matches > 1) | ||
return error("Not tracking: ambiguous information for ref %s", | ||
orig_ref); | ||
|
||
if (tracking.matches == 1) { | ||
sprintf(key, "branch.%s.remote", new_ref); | ||
git_config_set(key, tracking.remote ? tracking.remote : "."); | ||
sprintf(key, "branch.%s.merge", new_ref); | ||
git_config_set(key, tracking.src); | ||
free(tracking.src); | ||
printf("Branch %s set up to track remote branch %s.\n", | ||
new_ref, orig_ref); | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
void create_branch(const char *head, | ||
const char *name, const char *start_name, | ||
int force, int reflog, int track) | ||
{ | ||
struct ref_lock *lock; | ||
struct commit *commit; | ||
unsigned char sha1[20]; | ||
char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20]; | ||
int forcing = 0; | ||
|
||
snprintf(ref, sizeof ref, "refs/heads/%s", name); | ||
if (check_ref_format(ref)) | ||
die("'%s' is not a valid branch name.", name); | ||
|
||
if (resolve_ref(ref, sha1, 1, NULL)) { | ||
if (!force) | ||
die("A branch named '%s' already exists.", name); | ||
else if (!is_bare_repository() && !strcmp(head, name)) | ||
die("Cannot force update the current branch."); | ||
forcing = 1; | ||
} | ||
|
||
real_ref = NULL; | ||
if (get_sha1(start_name, sha1)) | ||
die("Not a valid object name: '%s'.", start_name); | ||
|
||
switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) { | ||
case 0: | ||
/* Not branching from any existing branch */ | ||
real_ref = NULL; | ||
break; | ||
case 1: | ||
/* Unique completion -- good */ | ||
break; | ||
default: | ||
die("Ambiguous object name: '%s'.", start_name); | ||
break; | ||
} | ||
|
||
if ((commit = lookup_commit_reference(sha1)) == NULL) | ||
die("Not a valid branch point: '%s'.", start_name); | ||
hashcpy(sha1, commit->object.sha1); | ||
|
||
lock = lock_any_ref_for_update(ref, NULL, 0); | ||
if (!lock) | ||
die("Failed to lock ref for update: %s.", strerror(errno)); | ||
|
||
if (reflog) | ||
log_all_ref_updates = 1; | ||
|
||
if (forcing) | ||
snprintf(msg, sizeof msg, "branch: Reset from %s", | ||
start_name); | ||
else | ||
snprintf(msg, sizeof msg, "branch: Created from %s", | ||
start_name); | ||
|
||
/* When branching off a remote branch, set up so that git-pull | ||
automatically merges from there. So far, this is only done for | ||
remotes registered via .git/config. */ | ||
if (real_ref && track) | ||
setup_tracking(name, real_ref); | ||
|
||
if (write_ref_sha1(lock, sha1, msg) < 0) | ||
die("Failed to write ref: %s.", strerror(errno)); | ||
|
||
if (real_ref) | ||
free(real_ref); | ||
} | ||
|
||
void remove_branch_state(void) | ||
{ | ||
unlink(git_path("MERGE_HEAD")); | ||
unlink(git_path("rr-cache/MERGE_RR")); | ||
unlink(git_path("MERGE_MSG")); | ||
unlink(git_path("SQUASH_MSG")); | ||
} |
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,24 @@ | ||
#ifndef BRANCH_H | ||
#define BRANCH_H | ||
|
||
/* Functions for acting on the information about branches. */ | ||
|
||
/* | ||
* Creates a new branch, where head is the branch currently checked | ||
* out, name is the new branch name, start_name is the name of the | ||
* existing branch that the new branch should start from, force | ||
* enables overwriting an existing (non-head) branch, reflog creates a | ||
* reflog for the branch, and track causes the new branch to be | ||
* configured to merge the remote branch that start_name is a tracking | ||
* branch for (if any). | ||
*/ | ||
void create_branch(const char *head, const char *name, const char *start_name, | ||
int force, int reflog, int track); | ||
|
||
/* | ||
* Remove information about the state of working on the current | ||
* branch. (E.g., MERGE_HEAD) | ||
*/ | ||
void remove_branch_state(void); | ||
|
||
#endif |
Oops, something went wrong.