Add git-svn branch to allow branch creation in SVN repositories
[ew: fixed a warning to stderr causing t9108 to fail] Signed-off-by: Florian Ragwitz <rafl@debian.org> Signed-off-by: Deskin Miller <deskinm@umich.edu> Acked-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Florian Ragwitz committed
Oct 4, 2008 at 19:35 UTC
5de70efbd9236e44f122348ec2a1c2967d3bfde8
3 files changed
+128
-2
Documentation/git-svn.txt
+23
-1
@@ -149,6 +149,22 @@ and have no uncommitted changes.
149
is very strongly discouraged.
150
--
151
152
+'branch'::
153
+ Create a branch in the SVN repository.
154
+
155
+-m;;
156
+--message;;
157
+ Allows to specify the commit message.
158
+
159
+-t;;
160
+--tag;;
161
+ Create a tag by using the tags_subdir instead of the branches_subdir
162
+ specified during git svn init.
163
+
164
+'tag'::
165
+ Create a tag in the SVN repository. This is a shorthand for
166
+ 'branch -t'.
167
+
168
'log'::
169
This should make it easy to look up svn log messages when svn
170
users refer to -r/--revision numbers.
@@ -372,7 +388,8 @@ Passed directly to 'git-rebase' when using 'dcommit' if a
388
-n::
389
--dry-run::
390
375
-This can be used with the 'dcommit' and 'rebase' commands.
391
+This can be used with the 'dcommit', 'rebase', 'branch' and 'tag'
392
+commands.
393
394
For 'dcommit', print out the series of git arguments that would show
395
which diffs would be committed to SVN.
@@ -381,6 +398,9 @@ For 'rebase', display the local branch associated with the upstream svn
398
repository associated with the current branch and the URL of svn
399
repository that will be fetched from.
400
401
+For 'branch' and 'tag', display the urls that will be used for copying when
402
+creating the branch or tag.
403
+
404
--
405
406
ADVANCED OPTIONS
@@ -498,6 +518,8 @@ Tracking and contributing to an entire Subversion-managed project
518
git svn clone http://svn.example.com/project -T trunk -b branches -t tags
519
# View all branches and tags you have cloned:
520
git branch -r
521
+# Create a new branch in SVN
522
+ git svn branch waldo
523
# Reset your master to trunk (or any other branch, replacing 'trunk'
524
# with the appropriate name):
525
git reset --hard remotes/trunk
git-svn.perl
+46
-1
@@ -66,7 +66,7 @@ my ($_stdin, $_help, $_edit,
66
$_version, $_fetch_all, $_no_rebase,
67
$_merge, $_strategy, $_dry_run, $_local,
68
$_prefix, $_no_checkout, $_url, $_verbose,
69
- $_git_format, $_commit_url);
69
+ $_git_format, $_commit_url, $_tag);
70
$Git::SVN::_follow_parent = 1;
71
my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
72
'config-dir=s' => \$Git::SVN::Ra::config_dir,
@@ -131,6 +131,15 @@ my %cmd = (
131
'revision|r=i' => \$_revision,
132
'no-rebase' => \$_no_rebase,
133
%cmt_opts, %fc_opts } ],
134
+ branch => [ \&cmd_branch,
135
+ 'Create a branch in the SVN repository',
136
+ { 'message|m=s' => \$_message,
137
+ 'dry-run|n' => \$_dry_run,
138
+ 'tag|t' => \$_tag } ],
139
+ tag => [ sub { $_tag = 1; cmd_branch(@_) },
140
+ 'Create a tag in the SVN repository',
141
+ { 'message|m=s' => \$_message,
142
+ 'dry-run|n' => \$_dry_run } ],
143
'set-tree' => [ \&cmd_set_tree,
144
"Set an SVN repository to a git tree-ish",
145
{ 'stdin|' => \$_stdin, %cmt_opts, %fc_opts, } ],
@@ -537,6 +546,42 @@ sub cmd_dcommit {
546
unlink $gs->{index};
547
}
548
549
+sub cmd_branch {
550
+ my ($branch_name, $head) = @_;
551
+
552
+ unless (defined $branch_name && length $branch_name) {
553
+ die(($_tag ? "tag" : "branch") . " name required\n");
554
+ }
555
+ $head ||= 'HEAD';
556
+
557
+ my ($src, $rev, undef, $gs) = working_head_info($head);
558
+
559
+ my $remote = Git::SVN::read_all_remotes()->{svn};
560
+ my $glob = $remote->{ $_tag ? 'tags' : 'branches' };
561
+ my ($lft, $rgt) = @{ $glob->{path} }{qw/left right/};
562
+ my $dst = join '/', $remote->{url}, $lft, $branch_name, ($rgt || ());
563
+
564
+ my $ctx = SVN::Client->new(
565
+ auth => Git::SVN::Ra::_auth_providers(),
566
+ log_msg => sub {
567
+ ${ $_[0] } = defined $_message
568
+ ? $_message
569
+ : 'Create ' . ($_tag ? 'tag ' : 'branch ' )
570
+ . $branch_name;
571
+ },
572
+ );
573
+
574
+ eval {
575
+ $ctx->ls($dst, 'HEAD', 0);
576
+ } and die "branch ${branch_name} already exists\n";
577
+
578
+ print "Copying ${src} at r${rev} to ${dst}...\n";
579
+ $ctx->copy($src, $rev, $dst)
580
+ unless $_dry_run;
581
+
582
+ $gs->fetch_all;
583
+}
584
+
585
sub cmd_find_rev {
586
my $revision_or_hash = shift or die "SVN or git revision required ",
587
"as a command-line argument\n";
t/t9128-git-svn-cmd-branch.sh
new
+59
@@ -0,0 +1,59 @@
1
+#!/bin/sh
2
+#
3
+# Copyright (c) 2008 Deskin Miller
4
+#
5
+
6
+test_description='git svn partial-rebuild tests'
7
+. ./lib-git-svn.sh
8
+
9
+test_expect_success 'initialize svnrepo' '
10
+ mkdir import &&
11
+ (
12
+ cd import &&
13
+ mkdir trunk branches tags &&
14
+ cd trunk &&
15
+ echo foo > foo &&
16
+ cd .. &&
17
+ svn import -m "import for git-svn" . "$svnrepo" >/dev/null &&
18
+ cd .. &&
19
+ rm -rf import &&
20
+ svn co "$svnrepo"/trunk trunk &&
21
+ cd trunk &&
22
+ echo bar >> foo &&
23
+ svn ci -m "updated trunk" &&
24
+ cd .. &&
25
+ rm -rf trunk
26
+ )
27
+'
28
+
29
+test_expect_success 'import into git' '
30
+ git svn init --stdlayout "$svnrepo" &&
31
+ git svn fetch &&
32
+ git checkout remotes/trunk
33
+'
34
+
35
+test_expect_success 'git svn branch tests' '
36
+ git svn branch a &&
37
+ base=$(git rev-parse HEAD:) &&
38
+ test $base = $(git rev-parse remotes/a:) &&
39
+ git svn branch -m "created branch b blah" b &&
40
+ test $base = $(git rev-parse remotes/b:) &&
41
+ test_must_fail git branch -m "no branchname" &&
42
+ git svn branch -n c &&
43
+ test_must_fail git rev-parse remotes/c &&
44
+ test_must_fail git svn branch a &&
45
+ git svn branch -t tag1 &&
46
+ test $base = $(git rev-parse remotes/tags/tag1:) &&
47
+ git svn branch --tag tag2 &&
48
+ test $base = $(git rev-parse remotes/tags/tag2:) &&
49
+ git svn tag tag3 &&
50
+ test $base = $(git rev-parse remotes/tags/tag3:) &&
51
+ git svn tag -m "created tag4 foo" tag4 &&
52
+ test $base = $(git rev-parse remotes/tags/tag4:) &&
53
+ test_must_fail git svn tag -m "no tagname" &&
54
+ git svn tag -n tag5 &&
55
+ test_must_fail git rev-parse remotes/tags/tag5 &&
56
+ test_must_fail git svn tag tag1
57
+'
58
+
59
+test_done