Skip to content

Commit 5a4d707

Browse files
committed
Merge branch 'db/checkout'
* 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
2 parents 992221d + 04c9e11 commit 5a4d707

20 files changed

+1002
-271
lines changed

Makefile

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ BASIC_CFLAGS =
226226
BASIC_LDFLAGS =
227227

228228
SCRIPT_SH = \
229-
git-bisect.sh git-checkout.sh \
229+
git-bisect.sh \
230230
git-clone.sh \
231231
git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
232232
git-pull.sh git-rebase.sh git-rebase--interactive.sh \
@@ -265,23 +265,23 @@ PROGRAMS = \
265265
git-upload-pack$X \
266266
git-pack-redundant$X git-var$X \
267267
git-merge-tree$X git-imap-send$X \
268-
git-merge-recursive$X \
269268
$(EXTRA_PROGRAMS)
270269

271270
# Empty...
272271
EXTRA_PROGRAMS =
273272

273+
# List built-in command $C whose implementation cmd_$C() is not in
274+
# builtin-$C.o but is linked in as part of some other command.
274275
BUILT_INS = \
275276
git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
276277
git-get-tar-commit-id$X git-init$X git-repo-config$X \
277278
git-fsck-objects$X git-cherry-pick$X git-peek-remote$X git-status$X \
279+
git-merge-subtree$X \
278280
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
279281

280282
# what 'all' will build and 'install' will install, in gitexecdir
281283
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
282284

283-
ALL_PROGRAMS += git-merge-subtree$X
284-
285285
# what 'all' will build but not install in gitexecdir
286286
OTHER_PROGRAMS = git$X gitweb/gitweb.cgi
287287

@@ -327,7 +327,7 @@ LIB_OBJS = \
327327
alloc.o merge-file.o path-list.o help.o unpack-trees.o $(DIFF_OBJS) \
328328
color.o wt-status.o archive-zip.o archive-tar.o shallow.o utf8.o \
329329
convert.o attr.o decorate.o progress.o mailmap.o symlinks.o remote.o \
330-
transport.o bundle.o walker.o parse-options.o ws.o archive.o \
330+
transport.o bundle.o walker.o parse-options.o ws.o archive.o branch.o \
331331
alias.o
332332

333333
BUILTIN_OBJS = \
@@ -340,6 +340,7 @@ BUILTIN_OBJS = \
340340
builtin-bundle.o \
341341
builtin-cat-file.o \
342342
builtin-check-attr.o \
343+
builtin-checkout.o \
343344
builtin-checkout-index.o \
344345
builtin-check-ref-format.o \
345346
builtin-clean.o \
@@ -370,6 +371,7 @@ BUILTIN_OBJS = \
370371
builtin-merge-base.o \
371372
builtin-merge-file.o \
372373
builtin-merge-ours.o \
374+
builtin-merge-recursive.o \
373375
builtin-mv.o \
374376
builtin-name-rev.o \
375377
builtin-pack-objects.o \
@@ -840,9 +842,6 @@ help.o: help.c common-cmds.h GIT-CFLAGS
840842
'-DGIT_MAN_PATH="$(mandir_SQ)"' \
841843
'-DGIT_INFO_PATH="$(infodir_SQ)"' $<
842844

843-
git-merge-subtree$X: git-merge-recursive$X
844-
$(QUIET_BUILT_IN)$(RM) $@ && ln git-merge-recursive$X $@
845-
846845
$(BUILT_INS): git$X
847846
$(QUIET_BUILT_IN)$(RM) $@ && ln git$X $@
848847

branch.c

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#include "cache.h"
2+
#include "branch.h"
3+
#include "refs.h"
4+
#include "remote.h"
5+
#include "commit.h"
6+
7+
struct tracking {
8+
struct refspec spec;
9+
char *src;
10+
const char *remote;
11+
int matches;
12+
};
13+
14+
static int find_tracked_branch(struct remote *remote, void *priv)
15+
{
16+
struct tracking *tracking = priv;
17+
18+
if (!remote_find_tracking(remote, &tracking->spec)) {
19+
if (++tracking->matches == 1) {
20+
tracking->src = tracking->spec.src;
21+
tracking->remote = remote->name;
22+
} else {
23+
free(tracking->spec.src);
24+
if (tracking->src) {
25+
free(tracking->src);
26+
tracking->src = NULL;
27+
}
28+
}
29+
tracking->spec.src = NULL;
30+
}
31+
32+
return 0;
33+
}
34+
35+
/*
36+
* This is called when new_ref is branched off of orig_ref, and tries
37+
* to infer the settings for branch.<new_ref>.{remote,merge} from the
38+
* config.
39+
*/
40+
static int setup_tracking(const char *new_ref, const char *orig_ref)
41+
{
42+
char key[1024];
43+
struct tracking tracking;
44+
45+
if (strlen(new_ref) > 1024 - 7 - 7 - 1)
46+
return error("Tracking not set up: name too long: %s",
47+
new_ref);
48+
49+
memset(&tracking, 0, sizeof(tracking));
50+
tracking.spec.dst = (char *)orig_ref;
51+
if (for_each_remote(find_tracked_branch, &tracking) ||
52+
!tracking.matches)
53+
return 1;
54+
55+
if (tracking.matches > 1)
56+
return error("Not tracking: ambiguous information for ref %s",
57+
orig_ref);
58+
59+
if (tracking.matches == 1) {
60+
sprintf(key, "branch.%s.remote", new_ref);
61+
git_config_set(key, tracking.remote ? tracking.remote : ".");
62+
sprintf(key, "branch.%s.merge", new_ref);
63+
git_config_set(key, tracking.src);
64+
free(tracking.src);
65+
printf("Branch %s set up to track remote branch %s.\n",
66+
new_ref, orig_ref);
67+
}
68+
69+
return 0;
70+
}
71+
72+
void create_branch(const char *head,
73+
const char *name, const char *start_name,
74+
int force, int reflog, int track)
75+
{
76+
struct ref_lock *lock;
77+
struct commit *commit;
78+
unsigned char sha1[20];
79+
char *real_ref, ref[PATH_MAX], msg[PATH_MAX + 20];
80+
int forcing = 0;
81+
82+
snprintf(ref, sizeof ref, "refs/heads/%s", name);
83+
if (check_ref_format(ref))
84+
die("'%s' is not a valid branch name.", name);
85+
86+
if (resolve_ref(ref, sha1, 1, NULL)) {
87+
if (!force)
88+
die("A branch named '%s' already exists.", name);
89+
else if (!is_bare_repository() && !strcmp(head, name))
90+
die("Cannot force update the current branch.");
91+
forcing = 1;
92+
}
93+
94+
real_ref = NULL;
95+
if (get_sha1(start_name, sha1))
96+
die("Not a valid object name: '%s'.", start_name);
97+
98+
switch (dwim_ref(start_name, strlen(start_name), sha1, &real_ref)) {
99+
case 0:
100+
/* Not branching from any existing branch */
101+
real_ref = NULL;
102+
break;
103+
case 1:
104+
/* Unique completion -- good */
105+
break;
106+
default:
107+
die("Ambiguous object name: '%s'.", start_name);
108+
break;
109+
}
110+
111+
if ((commit = lookup_commit_reference(sha1)) == NULL)
112+
die("Not a valid branch point: '%s'.", start_name);
113+
hashcpy(sha1, commit->object.sha1);
114+
115+
lock = lock_any_ref_for_update(ref, NULL, 0);
116+
if (!lock)
117+
die("Failed to lock ref for update: %s.", strerror(errno));
118+
119+
if (reflog)
120+
log_all_ref_updates = 1;
121+
122+
if (forcing)
123+
snprintf(msg, sizeof msg, "branch: Reset from %s",
124+
start_name);
125+
else
126+
snprintf(msg, sizeof msg, "branch: Created from %s",
127+
start_name);
128+
129+
/* When branching off a remote branch, set up so that git-pull
130+
automatically merges from there. So far, this is only done for
131+
remotes registered via .git/config. */
132+
if (real_ref && track)
133+
setup_tracking(name, real_ref);
134+
135+
if (write_ref_sha1(lock, sha1, msg) < 0)
136+
die("Failed to write ref: %s.", strerror(errno));
137+
138+
if (real_ref)
139+
free(real_ref);
140+
}
141+
142+
void remove_branch_state(void)
143+
{
144+
unlink(git_path("MERGE_HEAD"));
145+
unlink(git_path("rr-cache/MERGE_RR"));
146+
unlink(git_path("MERGE_MSG"));
147+
unlink(git_path("SQUASH_MSG"));
148+
}

branch.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef BRANCH_H
2+
#define BRANCH_H
3+
4+
/* Functions for acting on the information about branches. */
5+
6+
/*
7+
* Creates a new branch, where head is the branch currently checked
8+
* out, name is the new branch name, start_name is the name of the
9+
* existing branch that the new branch should start from, force
10+
* enables overwriting an existing (non-head) branch, reflog creates a
11+
* reflog for the branch, and track causes the new branch to be
12+
* configured to merge the remote branch that start_name is a tracking
13+
* branch for (if any).
14+
*/
15+
void create_branch(const char *head, const char *name, const char *start_name,
16+
int force, int reflog, int track);
17+
18+
/*
19+
* Remove information about the state of working on the current
20+
* branch. (E.g., MERGE_HEAD)
21+
*/
22+
void remove_branch_state(void);
23+
24+
#endif

0 commit comments

Comments
 (0)