= For Twisted contributors = If you want to develop a patch for Twisted (as described in the BasicGuideToContributingCode) but prefer to use Git rather than SVN, this is the section for you. For other version control systems, see [wiki:VcsWorkflows DVCS Workflows]. == Creating a Git clone == Twisted has an up-to-date [https://github.com/twisted/twisted mirror] on github. 1. Create a Git clone of the repository by running this command: {{{ git clone https://github.com/twisted/twisted Twisted }}} This should create a subdirectory named `Twisted` containing the latest trunk revision of the code. 1. Create an ignore file that will prevent git from accidentally scooping up generated files like `*.pyc` or `_trial_temp` and including them in any patches you might submit: {{{ cat >> Twisted/.git/info/exclude << EOF *.py[co] _trial_temp dropin.cache *.o *.lo *.la EOF }}} See [http://www.kernel.org/pub/software/scm/git/docs/gitignore.html the Git documentation on .gitignore], particularly `core.excludesfile`, for more information. 1. Since Twisted is normally developed in SVN, Twisted developers are used to processing SVN-style patch files, not Git's patch format. You can change the behaviour of `git diff` to match SVN just for this single repository with the following commands: {{{ git config --file Twisted/.git/config --bool --add diff.noprefix true }}} == Updating your Git clone == If more commits have been made to the SVN trunk, or a Twisted developer has created a new branch for your patch to live on, you'll want to update your clone with those changes so that you can produce new patches based on those changes. Just `cd` into the repository and run: {{{ git fetch git checkout master git rebase origin/trunk }}} == Generating patches == While on the branch for which you want to generate a diff {{{ git diff origin... > destroy-the-sun.patch }}} or, if there is already a branch in svn, {{{ git fetch git diff origin/destroy-the-sun-5000.. > destroy-the-sun-v666.patch }}} and then attach the patch to the appropriate ticket. ---- = For Twisted core developers = == Creating a complete mirror == To be able to interact with svn, the following commands need to be run in the repository created above. {{{ git svn init --stdlayout --tags tags/releases --prefix origin/ svn://svn.twistedmatrix.com/svn/Twisted/ git config --add svn-remote.svn.pushurl svn+ssh://svn.twistedmatrix.com/svn/Twisted/ }}} Twisted does not completely follow the standard SVN repository layout. In particular, there is a "branches/releases" directory that contains more branches (as opposed to being a branch) and a "tags/releases" directory that contains more tags (as opposed to being a tag). Thus, git cannot be used to commit to release branches. == git svn branching == Follow the [http://twistedmatrix.com/documents/current/core/development/policy/svn-dev.html#auto6 standard Twisted branch-name conventions] when creating branches with Git. I (tom.prince) currently use the following `mkbranch` script to create branches. {{{ #!/usr/bin/python import sys import subprocess from twisted.python import usage class Options(usage.Options): def parseArgs(self, branch): self.branch = branch if __name__ == '__main__': options = Options() try: options.parseOptions() except usage.UsageError as errortext: print '%s: %s' % (sys.argv[0], errortext) print '%s: Try --help for usage details.' % (sys.argv[0]) sys.exit(1) subprocess.check_call([ 'svn', 'cp', 'svn+ssh://svn.twistedmatrix.com/svn/Twisted/trunk', 'svn+ssh://svn.twistedmatrix.com/svn/Twisted/branches/%s' % (options.branch,), '-m', 'Branching to %s.' % (options.branch), ]) }}} I call it as follows {{{ mkbranch $BRANCH_NAME git fetch git checkout $BRANCH_NAME }}} An older version of this document had the following, which I haven't tested. In the following example, `$BRANCH_NAME` means the name of the branch you're trying to create. {{{ # Create "branches/$BRANCH_NAME" in the central SVN repository. git svn branch $BRANCH_NAME # Create and checkout local branch "$BRANCH_NAME" that tracks "remotes/$BRANCH_NAME" git checkout $BRANCH_NAME }}} == git svn committing == `git commit` only makes local commits. To get commits into svn, {{{ git svn dcommit --dry }}} will (update git-svn's metadata cache and) show where git will try to commit, and the list of commits it will push. {{{ git svn dcommit }}} will actually push the changes to svn. No special rules apply about making Git commits, you can make as many commits as you like, then rebase them into a nice patch series as normal (although the Twisted review process generally reviews the diff of an entire branch, not individual commits, since rebasing isn't possible in SVN). However, once you send your patches to the central SVN server with `git svn dcommit`, be very careful about messing with them. Don't rebase any further back than the last push, or else the next `dcommit` is likely to go awry. Likewise, if you merge from trunk to branch, then `dcommit` the merge, it will become an ordinary commit that doesn't remember its ancestry, and merging it back onto the trunk later is likely to cause grief. So don't do that. == git svn merging forward == {{{ mkbranch $BRANCH_NAME-2 git merge --squash origin/$BRANCH_NAME git commit -m'Merging forward' git svn dcommit }}} == git svn branch merging == In the following example, `$BRANCH_NAME` means the name of the branch you're trying to merge to trunk. {{{ # Check out the trunk (what git calls 'master'), make sure it's up-to-date. git checkout origin/trunk # Apply all the changes on the branch to the trunk as one change set. git merge --squash origin/$BRANCH_NAME # Commit the change set. Remember to use the Canonical Merge Commit Message Format! git commit # Push the commit to the central SVN repository. git svn dcommit }}} By "Canonical Merge Commit Message Format", I mean the example merge commit message in [http://twistedmatrix.com/documents/current/core/development/policy/svn-dev.html#auto6 the Working From Twisted's Subversion Repository documentation].