├── CHANGELOG.txt ├── LICENSE.txt ├── README.txt ├── fetch-svn-authors.sh ├── git-svn-migrate.sh ├── sample-repository-list.txt └── svn-lookup-author.sh /CHANGELOG.txt: -------------------------------------------------------------------------------- 1 | Version 1.x 2 | ----------- 3 | - Add option to make shared git repositories 4 | - Don't use --no-metadata by default, but show it as an usage option 5 | - Add ability to pass options to git-svn directly 6 | - Allow git-svn-migrate to be called from any directory 7 | - Make dependency on bash explicit 8 | 9 | Version 1.0 10 | ----------- 11 | - Initial release 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | 3 | Version 2, June 1991 4 | 5 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, 6 | Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute 7 | verbatim copies of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your freedom to 12 | share and change it. By contrast, the GNU General Public License is 13 | intended to guarantee your freedom to share and change free software--to 14 | make sure the software is free for all its users. This General Public License 15 | applies to most of the Free Software Foundation's software and to any other 16 | program whose authors commit to using it. (Some other Free Software 17 | Foundation software is covered by the GNU Library General Public License 18 | instead.) You can apply it to your programs, too. 19 | 20 | When we speak of free software, we are referring to freedom, not price. Our 21 | General Public Licenses are designed to make sure that you have the 22 | freedom to distribute copies of free software (and charge for this service if 23 | you wish), that you receive source code or can get it if you want it, that you 24 | can change the software or use pieces of it in new free programs; and that 25 | you know you can do these things. 26 | 27 | To protect your rights, we need to make restrictions that forbid anyone to 28 | deny you these rights or to ask you to surrender the rights. These restrictions 29 | translate to certain responsibilities for you if you distribute copies of the 30 | software, or if you modify it. 31 | 32 | For example, if you distribute copies of such a program, whether gratis or for 33 | a fee, you must give the recipients all the rights that you have. You must make 34 | sure that they, too, receive or can get the source code. And you must show 35 | them these terms so they know their rights. 36 | 37 | We protect your rights with two steps: (1) copyright the software, and (2) 38 | offer you this license which gives you legal permission to copy, distribute 39 | and/or modify the software. 40 | 41 | Also, for each author's protection and ours, we want to make certain that 42 | everyone understands that there is no warranty for this free software. If the 43 | software is modified by someone else and passed on, we want its recipients 44 | to know that what they have is not the original, so that any problems 45 | introduced by others will not reflect on the original authors' reputations. 46 | 47 | Finally, any free program is threatened constantly by software patents. We 48 | wish to avoid the danger that redistributors of a free program will individually 49 | obtain patent licenses, in effect making the program proprietary. To prevent 50 | this, we have made it clear that any patent must be licensed for everyone's 51 | free use or not licensed at all. 52 | 53 | The precise terms and conditions for copying, distribution and modification 54 | follow. 55 | 56 | GNU GENERAL PUBLIC LICENSE 57 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND 58 | MODIFICATION 59 | 60 | 0. This License applies to any program or other work which contains a notice 61 | placed by the copyright holder saying it may be distributed under the terms 62 | of this General Public License. The "Program", below, refers to any such 63 | program or work, and a "work based on the Program" means either the 64 | Program or any derivative work under copyright law: that is to say, a work 65 | containing the Program or a portion of it, either verbatim or with 66 | modifications and/or translated into another language. (Hereinafter, translation 67 | is included without limitation in the term "modification".) Each licensee is 68 | addressed as "you". 69 | 70 | Activities other than copying, distribution and modification are not covered 71 | by this License; they are outside its scope. The act of running the Program is 72 | not restricted, and the output from the Program is covered only if its contents 73 | constitute a work based on the Program (independent of having been made 74 | by running the Program). Whether that is true depends on what the Program 75 | does. 76 | 77 | 1. You may copy and distribute verbatim copies of the Program's source 78 | code as you receive it, in any medium, provided that you conspicuously and 79 | appropriately publish on each copy an appropriate copyright notice and 80 | disclaimer of warranty; keep intact all the notices that refer to this License 81 | and to the absence of any warranty; and give any other recipients of the 82 | Program a copy of this License along with the Program. 83 | 84 | You may charge a fee for the physical act of transferring a copy, and you 85 | may at your option offer warranty protection in exchange for a fee. 86 | 87 | 2. You may modify your copy or copies of the Program or any portion of it, 88 | thus forming a work based on the Program, and copy and distribute such 89 | modifications or work under the terms of Section 1 above, provided that you 90 | also meet all of these conditions: 91 | 92 | a) You must cause the modified files to carry prominent notices stating that 93 | you changed the files and the date of any change. 94 | 95 | b) You must cause any work that you distribute or publish, that in whole or in 96 | part contains or is derived from the Program or any part thereof, to be 97 | licensed as a whole at no charge to all third parties under the terms of this 98 | License. 99 | 100 | c) If the modified program normally reads commands interactively when run, 101 | you must cause it, when started running for such interactive use in the most 102 | ordinary way, to print or display an announcement including an appropriate 103 | copyright notice and a notice that there is no warranty (or else, saying that 104 | you provide a warranty) and that users may redistribute the program under 105 | these conditions, and telling the user how to view a copy of this License. 106 | (Exception: if the Program itself is interactive but does not normally print such 107 | an announcement, your work based on the Program is not required to print 108 | an announcement.) 109 | 110 | These requirements apply to the modified work as a whole. If identifiable 111 | sections of that work are not derived from the Program, and can be 112 | reasonably considered independent and separate works in themselves, then 113 | this License, and its terms, do not apply to those sections when you distribute 114 | them as separate works. But when you distribute the same sections as part 115 | of a whole which is a work based on the Program, the distribution of the 116 | whole must be on the terms of this License, whose permissions for other 117 | licensees extend to the entire whole, and thus to each and every part 118 | regardless of who wrote it. 119 | 120 | Thus, it is not the intent of this section to claim rights or contest your rights to 121 | work written entirely by you; rather, the intent is to exercise the right to 122 | control the distribution of derivative or collective works based on the 123 | Program. 124 | 125 | In addition, mere aggregation of another work not based on the Program 126 | with the Program (or with a work based on the Program) on a volume of a 127 | storage or distribution medium does not bring the other work under the scope 128 | of this License. 129 | 130 | 3. You may copy and distribute the Program (or a work based on it, under 131 | Section 2) in object code or executable form under the terms of Sections 1 132 | and 2 above provided that you also do one of the following: 133 | 134 | a) Accompany it with the complete corresponding machine-readable source 135 | code, which must be distributed under the terms of Sections 1 and 2 above 136 | on a medium customarily used for software interchange; or, 137 | 138 | b) Accompany it with a written offer, valid for at least three years, to give 139 | any third party, for a charge no more than your cost of physically performing 140 | source distribution, a complete machine-readable copy of the corresponding 141 | source code, to be distributed under the terms of Sections 1 and 2 above on 142 | a medium customarily used for software interchange; or, 143 | 144 | c) Accompany it with the information you received as to the offer to distribute 145 | corresponding source code. (This alternative is allowed only for 146 | noncommercial distribution and only if you received the program in object 147 | code or executable form with such an offer, in accord with Subsection b 148 | above.) 149 | 150 | The source code for a work means the preferred form of the work for 151 | making modifications to it. For an executable work, complete source code 152 | means all the source code for all modules it contains, plus any associated 153 | interface definition files, plus the scripts used to control compilation and 154 | installation of the executable. However, as a special exception, the source 155 | code distributed need not include anything that is normally distributed (in 156 | either source or binary form) with the major components (compiler, kernel, 157 | and so on) of the operating system on which the executable runs, unless that 158 | component itself accompanies the executable. 159 | 160 | If distribution of executable or object code is made by offering access to 161 | copy from a designated place, then offering equivalent access to copy the 162 | source code from the same place counts as distribution of the source code, 163 | even though third parties are not compelled to copy the source along with the 164 | object code. 165 | 166 | 4. You may not copy, modify, sublicense, or distribute the Program except as 167 | expressly provided under this License. Any attempt otherwise to copy, 168 | modify, sublicense or distribute the Program is void, and will automatically 169 | terminate your rights under this License. However, parties who have received 170 | copies, or rights, from you under this License will not have their licenses 171 | terminated so long as such parties remain in full compliance. 172 | 173 | 5. You are not required to accept this License, since you have not signed it. 174 | However, nothing else grants you permission to modify or distribute the 175 | Program or its derivative works. These actions are prohibited by law if you 176 | do not accept this License. Therefore, by modifying or distributing the 177 | Program (or any work based on the Program), you indicate your acceptance 178 | of this License to do so, and all its terms and conditions for copying, 179 | distributing or modifying the Program or works based on it. 180 | 181 | 6. Each time you redistribute the Program (or any work based on the 182 | Program), the recipient automatically receives a license from the original 183 | licensor to copy, distribute or modify the Program subject to these terms and 184 | conditions. You may not impose any further restrictions on the recipients' 185 | exercise of the rights granted herein. You are not responsible for enforcing 186 | compliance by third parties to this License. 187 | 188 | 7. If, as a consequence of a court judgment or allegation of patent 189 | infringement or for any other reason (not limited to patent issues), conditions 190 | are imposed on you (whether by court order, agreement or otherwise) that 191 | contradict the conditions of this License, they do not excuse you from the 192 | conditions of this License. If you cannot distribute so as to satisfy 193 | simultaneously your obligations under this License and any other pertinent 194 | obligations, then as a consequence you may not distribute the Program at all. 195 | For example, if a patent license would not permit royalty-free redistribution 196 | of the Program by all those who receive copies directly or indirectly through 197 | you, then the only way you could satisfy both it and this License would be to 198 | refrain entirely from distribution of the Program. 199 | 200 | If any portion of this section is held invalid or unenforceable under any 201 | particular circumstance, the balance of the section is intended to apply and 202 | the section as a whole is intended to apply in other circumstances. 203 | 204 | It is not the purpose of this section to induce you to infringe any patents or 205 | other property right claims or to contest validity of any such claims; this 206 | section has the sole purpose of protecting the integrity of the free software 207 | distribution system, which is implemented by public license practices. Many 208 | people have made generous contributions to the wide range of software 209 | distributed through that system in reliance on consistent application of that 210 | system; it is up to the author/donor to decide if he or she is willing to 211 | distribute software through any other system and a licensee cannot impose 212 | that choice. 213 | 214 | This section is intended to make thoroughly clear what is believed to be a 215 | consequence of the rest of this License. 216 | 217 | 8. If the distribution and/or use of the Program is restricted in certain 218 | countries either by patents or by copyrighted interfaces, the original copyright 219 | holder who places the Program under this License may add an explicit 220 | geographical distribution limitation excluding those countries, so that 221 | distribution is permitted only in or among countries not thus excluded. In such 222 | case, this License incorporates the limitation as if written in the body of this 223 | License. 224 | 225 | 9. The Free Software Foundation may publish revised and/or new versions 226 | of the General Public License from time to time. Such new versions will be 227 | similar in spirit to the present version, but may differ in detail to address new 228 | problems or concerns. 229 | 230 | Each version is given a distinguishing version number. If the Program specifies 231 | a version number of this License which applies to it and "any later version", 232 | you have the option of following the terms and conditions either of that 233 | version or of any later version published by the Free Software Foundation. If 234 | the Program does not specify a version number of this License, you may 235 | choose any version ever published by the Free Software Foundation. 236 | 237 | 10. If you wish to incorporate parts of the Program into other free programs 238 | whose distribution conditions are different, write to the author to ask for 239 | permission. For software which is copyrighted by the Free Software 240 | Foundation, write to the Free Software Foundation; we sometimes make 241 | exceptions for this. Our decision will be guided by the two goals of 242 | preserving the free status of all derivatives of our free software and of 243 | promoting the sharing and reuse of software generally. 244 | 245 | NO WARRANTY 246 | 247 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 248 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT 249 | PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE 250 | STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 251 | OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT 252 | WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, 253 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 254 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 255 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 256 | PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 257 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL 258 | NECESSARY SERVICING, REPAIR OR CORRECTION. 259 | 260 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR 261 | AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR 262 | ANY OTHER PARTY WHO MAY MODIFY AND/OR 263 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE 264 | LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, 265 | SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES 266 | ARISING OUT OF THE USE OR INABILITY TO USE THE 267 | PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA 268 | OR DATA BEING RENDERED INACCURATE OR LOSSES 269 | SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE 270 | PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN 271 | IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF 272 | THE POSSIBILITY OF SUCH DAMAGES. 273 | 274 | END OF TERMS AND CONDITIONS 275 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | ABOUT git-svn-migrate 2 | --------------------- 3 | 4 | The git-svn-migrate project is a set of helper scripts to ease the migration of 5 | Subversion repositories to Git. 6 | 7 | The basic steps to converting a list of Subversion repositories into Git 8 | repositories are the following: 9 | 10 | 1. Create a list of Subversion repositories to convert. 11 | 12 | 2. Create a list of transformations for Subversion usernames to Git committers. 13 | Run: 14 | ./fetch-svn-authors.sh --url-file=[filename] > [output file for raw authors] 15 | 16 | Then edit the raw list of Subversion usernames to provide full names and 17 | emails suitable for Git committers. 18 | 19 | 3. Convert the Subversion repositories into bare Git repositories with: 20 | ./git-svn-migrate.sh --url-file=[filename] --authors-file=[filename] [destination folder] 21 | 22 | A blog post about these migration scripts and a blog post about the underlying 23 | techniques are available at: 24 | http://john.albin.net/git/git-svn-migrate 25 | http://john.albin.net/git/convert-subversion-to-git 26 | 27 | 28 | USAGE 29 | ----- 30 | 31 | 1. Create a list of Subversion repositories to convert. 32 | 33 | The repository list should just be a plain text file with one repository per 34 | line. Each line can be in one of two formats. The basic format is simply the 35 | repository's URL by itself: 36 | 37 | svn+ssh://example.org/svn/awesomeProject 38 | file:///svn/secretProject 39 | https://example.com/svn/evilProject 40 | 41 | With this format the name of the project is assumed to be the last part of the 42 | URL. So these repositories would be converted into awesomeProject.git, 43 | secretProject.git and evilProject.git, respectively. 44 | 45 | If the project name of your repository is not the last part of the URL, or you 46 | wish to have more control over the final name of the Git repository, you can 47 | specify the repository list in tab-delimited format with the first field being 48 | the name to give the Git repository and the second field being the URL of the 49 | Subversion repository: 50 | 51 | awesomeProject svn+ssh://example.org/svn/awesomeProject/repo 52 | evilproject file:///svn/evilProject 53 | notthedroidsyourlookingfor https://example.com/svn/secretProject 54 | 55 | With this format you can use any name for the final Git repo. In the first 56 | example above, we're using the second-to-last part of the URL instead of the 57 | last part of the URL. In the second example, we're just changing the name to all 58 | lowercase (recommended). And in the final example, move along. Move along. 59 | 60 | 2. Create a list of transformations for Subversion usernames to Git committers. 61 | 62 | Using the repository list created in step 1, run the fetch-svn-authors.sh script 63 | to create a list of unique usernames for all the commits in your repositories. 64 | The output of the script should be redirected to a file. 65 | 66 | Example (assuming your repository list is in "repository-list.txt"): 67 | 68 | $ ./fetch-svn-authors.sh --url-file=repository-list.txt > author-transform.txt 69 | 70 | Edit the raw list of Subversion usernames to provide full names and emails 71 | suitable for Git committers. The output of the fetch-svn-authors.sh script will 72 | be of the form: 73 | username = username 74 | You should edit each line to be: 75 | username = Full name 76 | 77 | For example: 78 | change: 79 | jwilkins = jwilkins 80 | into: 81 | jwilkins = John Albin Wilkins 82 | 83 | You can run "./fetch-svn-authors.sh --help" to get full documentation on the 84 | options it accepts. 85 | 86 | 3. Convert the Subversion repositories into bare Git repositories. 87 | 88 | Example: 89 | 90 | $ ./git-svn-migrate.sh --url-file=repository-list.txt --authors-file=author-transform.txt /var/git 91 | 92 | You can run "./git-svn-migrate.sh --help" to get full documentation on the 93 | options it accepts. 94 | 95 | 96 | AUTHENTICATION 97 | -------------- 98 | 99 | Authenticating with each of the repositories is out-of-scope for these scripts. 100 | You should ensure that all of the SVN repositories can be accessed 101 | non-interactively (i.e. no password prompts) in order for these scripts to work. 102 | If you consider this a bug, bugfixes are welcome! 103 | 104 | 105 | REQUIREMENTS 106 | ------------ 107 | 108 | - git 1.7 or later 109 | - Bash shell 110 | 111 | 112 | LICENSE 113 | ------- 114 | 115 | Available under the GPL v2 license. See LICENSE.txt. 116 | -------------------------------------------------------------------------------- /fetch-svn-authors.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2010 John Albin Wilkins. 4 | # Available under the GPL v2 license. See LICENSE.txt. 5 | 6 | script=`basename $0`; 7 | usage=$(cat < --destination= 9 | \n 10 | \nFor more info, see: $script --help 11 | EOF_USAGE 12 | ); 13 | 14 | help=$(cat <, -u , 32 | \n\t--url-file=, --url-file 33 | \n\t\tSpecify the file containing the Subversion repository list. 34 | \n 35 | \n\t-a=, -a , 36 | \n\t--authors-file=[filename], --authors-file [filename] 37 | \n\t\tSpecify the file containing the authors transformation data. 38 | \n 39 | \n\t-d=, -d , --destination 41 | \n\t\tThe directory where the new Git repositories should be 42 | \n\t\tsaved. Defaults to the current directory. 43 | \n 44 | \nBASIC EXAMPLES 45 | \n\t# Use the long parameter names 46 | \n\t$script --url-file=my-repository-list.txt --destination=authors-file.txt 47 | \n 48 | \n\t# Use short parameter names and redirect standard output 49 | \n\t$script -u my-repository-list.txt > authors-file.txt 50 | \n 51 | \nSEE ALSO 52 | \n\tgit-svn-migrate.sh 53 | EOF_HELP 54 | ); 55 | 56 | 57 | # Set defaults for any optional parameters or arguments. 58 | destination=''; 59 | 60 | # Process parameters. 61 | until [[ -z "$1" ]]; do 62 | option=$1; 63 | # Strip off leading '--' or '-'. 64 | if [[ ${option:0:1} == '-' ]]; then 65 | if [[ ${option:0:2} == '--' ]]; then 66 | tmp=${option:2}; 67 | else 68 | tmp=${option:1}; 69 | fi 70 | else 71 | # Any argument given is assumed to be the destination folder. 72 | tmp="destination=$option"; 73 | fi 74 | parameter=${tmp%%=*}; # Extract option's name. 75 | value=${tmp##*=}; # Extract option's value. 76 | case $parameter in 77 | # Some parameters don't require a value. 78 | #no-minimize-url ) ;; 79 | 80 | # If a value is expected, but not specified inside the parameter, grab the next param. 81 | * ) 82 | if [[ $value == $tmp ]]; then 83 | if [[ ${2:0:1} == '-' ]]; then 84 | # The next parameter is a new option, so unset the value. 85 | value=''; 86 | else 87 | value=$2; 88 | shift; 89 | fi 90 | fi 91 | ;; 92 | esac 93 | 94 | case $parameter in 95 | u ) url_file=$value;; 96 | url-file ) url_file=$value;; 97 | d ) destination=$value;; 98 | destination ) destination=$value;; 99 | 100 | h ) echo $help | less >&2; exit;; 101 | help ) echo $help | less >&2; exit;; 102 | 103 | * ) echo "Unknown option: $option\n$usage" >&2; exit 1;; 104 | esac 105 | 106 | # Remove the processed parameter. 107 | shift; 108 | done 109 | 110 | # Check for required parameters. 111 | if [[ $url_file == '' ]]; then 112 | echo $usage >&2; 113 | exit 1; 114 | fi 115 | # Check for valid file. 116 | if [[ ! -f $url_file ]]; then 117 | echo "Specified URL file \"$url_file\" does not exist or is not a file." >&2; 118 | echo $usage >&2; 119 | exit 1; 120 | fi 121 | 122 | 123 | # Process each URL in the repository list. 124 | tmp_file="tmp-authors-transform.txt"; 125 | while read line 126 | do 127 | # Check for 2-field format: Name [tab] URL 128 | name=`echo $line | awk '{print $1}'`; 129 | url=`echo $line | awk '{print $2}'`; 130 | # Check for simple 1-field format: URL 131 | if [[ $url == '' ]]; then 132 | url=$name; 133 | name=`basename $url`; 134 | fi 135 | # Process the log of each Subversion URL. 136 | echo "Processing \"$name\" repository at $url..." >&2; 137 | /bin/echo -n " " >&2; 138 | svn log -q $url | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u >> $tmp_file; 139 | echo "Done." >&2; 140 | done < $url_file 141 | 142 | # Process temp file one last time to show results. 143 | if [[ $destination == '' ]]; then 144 | # Display on standard output. 145 | cat $tmp_file | sort -u; 146 | else 147 | # Output to the specified destination file. 148 | cat $tmp_file | sort -u > $destination; 149 | fi 150 | unlink $tmp_file; 151 | -------------------------------------------------------------------------------- /git-svn-migrate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2010-2011 John Albin Wilkins and contributors. 4 | # Available under the GPL v2 license. See LICENSE.txt. 5 | 6 | script=`basename $0`; 7 | dir=`pwd`/`dirname $0`; 8 | usage=$(cat < --authors-file= [destination folder] 10 | \n 11 | \nFor more info, see: $script --help 12 | EOF_USAGE 13 | ); 14 | 15 | help=$(cat <, -u , 32 | \n\t--url-file=, --url-file 33 | \n\t\tSpecify the file containing the Subversion repository list. 34 | \n 35 | \n\t-a=, -a , 36 | \n\t--authors-file=[filename], --authors-file [filename] 37 | \n\t\tSpecify the file containing the authors transformation data. 38 | \n 39 | \n\t-d=, -d , 40 | \n\t--destination=, --destination 41 | \n\t\tThe directory where the new Git repositories should be 42 | \n\t\tsaved. Defaults to the current directory. 43 | \n 44 | \n\t-i=, -i , 45 | \n\t--ignore-file=, --ignore-file 46 | \n\t\tThe location of a .gitignore file to add to all repositories. 47 | \n 48 | \n\t--quiet 49 | \n\t\tBy default this script is rather verbose since it outputs each revision 50 | \n\t\tnumber as it is processed from Subversion. Since conversion can sometimes 51 | \n\t\ttake hours to complete, this output can be useful. However, this option 52 | \n\t\twill surpress that output. 53 | \n 54 | \n\t--no-metadata 55 | \n\t\tBy default, all converted log messages will include a line starting with 56 | \n\t\t"git-svn-id:" which makes it easy to track down old references to 57 | \n\t\tSubversion revision numbers in existing documentation, bug reports and 58 | \n\t\tarchives. Use this option to get rid of that data. See git svn --help for 59 | \n\t\ta fuller discussion on this option. 60 | \n 61 | \n\t--shared[=(false|true|umask|group|all|world|everybody|0xxx)] 62 | \n\t\tSpecify that the generated git repositories are to be shared amongst 63 | \n\t\tseveral users. See git init --help for more info about this option. 64 | \n 65 | \n\tAny additional options are assumed to be git-svn options and will be passed 66 | \n\talong to that utility directly. Some useful git-svn options are: 67 | \n\t\t--trunk --tags --branches --no-minimize-url 68 | \n\tSee git svn --help for more info about its options. 69 | \n 70 | \nBASIC EXAMPLES 71 | \n\t# Use the long parameter names 72 | \n\t$script --url-file=my-repository-list.txt --authors-file=authors-file.txt --destination=/var/git 73 | \n 74 | \n\t# Use short parameter names 75 | \n\t$script -u my-repository-list.txt -a authors-file.txt /var/git 76 | \n 77 | \nSEE ALSO 78 | \n\tfetch-svn-authors.sh 79 | \n\tsvn-lookup-author.sh 80 | EOF_HELP 81 | ); 82 | 83 | 84 | # Set defaults for any optional parameters or arguments. 85 | destination='.'; 86 | gitinit_params=''; 87 | gitsvn_params=''; 88 | 89 | # Process parameters. 90 | until [[ -z "$1" ]]; do 91 | option=$1; 92 | # Strip off leading '--' or '-'. 93 | if [[ ${option:0:1} == '-' ]]; then 94 | flag_delimiter='-'; 95 | if [[ ${option:0:2} == '--' ]]; then 96 | tmp=${option:2}; 97 | flag_delimiter='--'; 98 | else 99 | tmp=${option:1}; 100 | fi 101 | else 102 | # Any argument given is assumed to be the destination folder. 103 | tmp="destination=$option"; 104 | fi 105 | parameter=${tmp%%=*}; # Extract option's name. 106 | value=${tmp##*=}; # Extract option's value. 107 | # If a value is expected, but not specified inside the parameter, grab the next param. 108 | if [[ $value == $tmp ]]; then 109 | if [[ ${2:0:1} == '-' ]]; then 110 | # The next parameter is a new option, so unset the value. 111 | value=''; 112 | else 113 | value=$2; 114 | shift; 115 | fi 116 | fi 117 | 118 | case $parameter in 119 | u ) url_file=$value;; 120 | url-file ) url_file=$value;; 121 | a ) authors_file=$value;; 122 | authors-file ) authors_file=$value;; 123 | d ) destination=$value;; 124 | destination ) destination=$value;; 125 | i ) ignore_file=$value;; 126 | ignore-file ) ignore_file=$value;; 127 | shared ) if [[ $value == '' ]]; then 128 | gitinit_params="--shared"; 129 | else 130 | gitinit_params="--shared=$value"; 131 | fi 132 | ;; 133 | 134 | h ) echo -e $help | less >&2; exit;; 135 | help ) echo -e $help | less >&2; exit;; 136 | 137 | * ) # Pass any unknown parameters to git-svn directly. 138 | if [[ $value == '' ]]; then 139 | gitsvn_params="$gitsvn_params $flag_delimiter$parameter"; 140 | else 141 | gitsvn_params="$gitsvn_params $flag_delimiter$parameter=$value"; 142 | fi;; 143 | esac 144 | 145 | # Remove the processed parameter. 146 | shift; 147 | done 148 | 149 | # Check for required parameters. 150 | if [[ $url_file == '' || $authors_file == '' ]]; then 151 | echo -e $usage >&2; 152 | exit 1; 153 | fi 154 | # Check for valid files. 155 | if [[ ! -f $url_file ]]; then 156 | echo "Specified URL file \"$url_file\" does not exist or is not a file." >&2; 157 | echo -e $usage >&2; 158 | exit 1; 159 | fi 160 | if [[ ! -f $authors_file ]]; then 161 | echo "Specified authors file \"$authors_file\" does not exist or is not a file." >&2; 162 | echo -e $usage >&2; 163 | exit 1; 164 | fi 165 | 166 | 167 | # Process each URL in the repository list. 168 | pwd=`pwd`; 169 | tmp_destination="$pwd/tmp-git-repo"; 170 | mkdir -p $destination; 171 | destination=`cd $destination; pwd`; #Absolute path. 172 | 173 | # Ensure temporary repository location is empty. 174 | if [[ -e $tmp_destination ]]; then 175 | echo "Temporary repository location \"$tmp_destination\" already exists. Exiting." >&2; 176 | exit 1; 177 | fi 178 | while read line 179 | do 180 | # Check for 2-field format: Name [tab] URL 181 | name=`echo $line | awk '{print $1}'`; 182 | url=`echo $line | awk '{print $2}'`; 183 | # Check for simple 1-field format: URL 184 | if [[ $url == '' ]]; then 185 | url=$name; 186 | name=`basename $url`; 187 | fi 188 | # Process each Subversion URL. 189 | echo >&2; 190 | echo "At $(date)..." >&2; 191 | echo "Processing \"$name\" repository at $url..." >&2; 192 | 193 | # Init the final bare repository. 194 | mkdir $destination/$name.git; 195 | cd $destination/$name.git; 196 | git init --bare $gitinit_params; 197 | git symbolic-ref HEAD refs/heads/trunk; 198 | 199 | # Clone the original Subversion repository to a temp repository. 200 | cd $pwd; 201 | echo "- Cloning repository..." >&2; 202 | git svn clone $url -A $authors_file --authors-prog=$dir/svn-lookup-author.sh --stdlayout --quiet $gitsvn_params $tmp_destination; 203 | 204 | # Create .gitignore file. 205 | echo "- Converting svn:ignore properties into a .gitignore file..." >&2; 206 | if [[ $ignore_file != '' ]]; then 207 | cp $ignore_file $tmp_destination/.gitignore; 208 | fi 209 | cd $tmp_destination; 210 | git svn show-ignore --id trunk >> .gitignore; 211 | git add .gitignore; 212 | git commit --author="git-svn-migrate " -m 'Convert svn:ignore properties to .gitignore.'; 213 | 214 | # Push to final bare repository and remove temp repository. 215 | echo "- Pushing to new bare repository..." >&2; 216 | git remote add bare $destination/$name.git; 217 | git config remote.bare.push 'refs/remotes/*:refs/heads/*'; 218 | git push bare; 219 | # Push the .gitignore commit that resides on master. 220 | git push bare master:trunk; 221 | cd $pwd; 222 | rm -r $tmp_destination; 223 | 224 | # Rename Subversion's "trunk" branch to Git's standard "master" branch. 225 | cd $destination/$name.git; 226 | git branch -m trunk master; 227 | 228 | # Remove bogus branches of the form "name@REV". 229 | git for-each-ref --format='%(refname)' refs/heads | grep '@[0-9][0-9]*' | cut -d / -f 3- | 230 | while read ref 231 | do 232 | git branch -D "$ref"; 233 | done 234 | 235 | # Convert git-svn tag branches to proper tags. 236 | echo "- Converting svn tag directories to proper git tags..." >&2; 237 | git for-each-ref --format='%(refname)' refs/heads/tags | cut -d / -f 4 | 238 | while read ref 239 | do 240 | git tag -a "$ref" -m "Convert \"$ref\" to a proper git tag." "refs/heads/tags/$ref"; 241 | git branch -D "tags/$ref"; 242 | done 243 | 244 | echo "- Conversion completed at $(date)." >&2; 245 | done < $url_file 246 | -------------------------------------------------------------------------------- /sample-repository-list.txt: -------------------------------------------------------------------------------- 1 | albin file:///svn/Albin 2 | awesomeProject svn+ssh://example.org/svn/awesomeProject/repo 3 | notSoEvilProject https://example.com/svn/evilestProjectEver 4 | file:///svn/secretProject 5 | -------------------------------------------------------------------------------- /svn-lookup-author.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2010 John Albin Wilkins. 4 | # Available under the GPL v2 license. See LICENSE.txt. 5 | 6 | # If the Subversion author is not found in authors list file, svn-git-migrate 7 | # will call this script with the username as the only parameter to try to 8 | # determine the proper Git user. Since we do not know the proper user, we simply 9 | # return "username ". 10 | # 11 | # You can modify this script to return whatever you think is appropriate for a 12 | # given username in your organization. 13 | echo "$1 <$1>"; 14 | --------------------------------------------------------------------------------