$ git svn clone file:///tmp/test-svn -T trunk -b branches -t tags
Initialized empty Git repository in /private/tmp/progit/test-svn/.git/
r1 =dcbfb5891860124cc2e8cc616cded42624897125(refs/remotes/origin/trunk)
A m4/acx_pthread.m4
A m4/stl_hash.m4
A java/src/test/java/com/google/protobuf/UnknownFieldSetTest.java
A java/src/test/java/com/google/protobuf/WireFormatTest.java
…
r75 =556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae(refs/remotes/origin/trunk)
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/my-calc-branch, 75
Found branch parent:(refs/remotes/origin/my-calc-branch)556a3e1e7ad1fde0a32823fc7e4d046bcfd86dae
Following parent with do_switch
Successfully followed parent
r76 =0fb585761df569eaecd8146c71e58d70147460a2(refs/remotes/origin/my-calc-branch)
Checked out HEAD:
file:///tmp/test-svn/trunk r75
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M README.txt
Committed r77
M README.txt
r77 =95e0222ba6399739834380eb10afcd73e0670bc5(refs/remotes/origin/trunk)
No changes between 4af61fd05045e07598c553167e0f31c84fd6ffe1 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: d5837c4b461b7c0e018b49d12398769d2bfc240a and refs/remotes/origin/trunk differ, using rebase::100644100644 f414c433af0fd6734428cf9d2a9fd8ba00ada145 c80b6127dd04f5fcda218730ddf3a2da4eb39138 M README.txt
Current branch master is up to date.
ERROR: Not all changes have been committed into SVN, however the committed
ones(if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.
$ git svn rebase
Committing to file:///tmp/test-svn/trunk ...
ERROR from SVN:
Transaction is out of date: File '/trunk/README.txt' is out of date
W: eaa029d99f87c5c822c5c29039d19111ff32ef46 and refs/remotes/origin/trunk differ, using rebase::10064410064465536c6e30d263495c17d781962cfff12422693a b34372b25ccf4945fe5658fa381b075045e7702a M README.txt
First, rewinding head to replay your work on top of it...
Applying: update foo
Using index info to reconstruct a base tree...
M README.txt
Falling back to patching base and 3-way merge...
Auto-merging README.txt
ERROR: Not all changes have been committed into SVN, however the committed
ones(if any) seem to be successfully integrated into the working tree.
Please see the above messages for details.
现在,所有的工作都已经在 Subversion 服务器的内容之上了,就可以顺利地 dcommit:
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M README.txt
Committed r85
M README.txt
r85 =9c29704cc0bbbed7bd58160cfb66cb9191835cd8(refs/remotes/origin/trunk)
No changes between 5762f56732a958d6cfda681b661d2a239cc53ef5 and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M configure.ac
Committed r87
M autogen.sh
r86 =d8450bab8a77228a644b7dc0e95977ffc61adff7(refs/remotes/origin/trunk)
M configure.ac
r87 =f3653ea40cb4e26b6281cec102e35dcba1fe17c4(refs/remotes/origin/trunk)
W: a0253d06732169107aa020390d9fefd2b1d92806 and refs/remotes/origin/trunk differ, using rebase::100755100755 efa5a59965fbbb5b2b0a12890f1b351bb5493c18 e757b59a9439312d80d5d43bb65d4a7d0389ed6d M autogen.sh
First, rewinding head to replay your work on top of it...
$ git svn rebase
M autogen.sh
r88 =c9c5f83c64bd755368784b444bc7a0216cc1e17b(refs/remotes/origin/trunk)
First, rewinding head to replay your work on top of it...
Fast-forwarded master to refs/remotes/origin/trunk.
每隔一会儿运行 git svn rebase 确保代码始终是最新的,虽然需要保证当运行这个命令时工作目录是干净的。如果有本地的修改,在运行 git svn rebase 之前要么储藏工作要么做一次临时的提交,不然当变基会导致合并冲突时,命令会终止。
$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
M CHANGES.txt
Committed r89
M CHANGES.txt
r89 =89d492c884ea7c834353563d5d913c6adf933981(refs/remotes/origin/trunk)
M COPYING.txt
M INSTALL.txt
Committed r90
M INSTALL.txt
M COPYING.txt
r90 =cb522197870e61467473391799148f6721bcf9a0(refs/remotes/origin/trunk)
No changes between 71af502c214ba13123992338569f4669877f55fd and refs/remotes/origin/trunk
Resetting to the latest refs/remotes/origin/trunk
$ git svn branch opera
Copying file:///tmp/test-svn/trunk at r90 to file:///tmp/test-svn/branches/opera...
Found possible branch point: file:///tmp/test-svn/trunk => file:///tmp/test-svn/branches/opera, 90
Found branch parent:(refs/remotes/origin/opera) cb522197870e61467473391799148f6721bcf9a0
Following parent with do_switch
Successfully followed parent
r91 =f1b64a3855d3c8dd84ee0ef10fa89d27f1584302(refs/remotes/origin/opera)
$ git svn info
Path:.
URL: https://schacon-test.googlecode.com/svn/trunk
Repository Root: https://schacon-test.googlecode.com/svn
Repository UUID:4c93b258-373f-11de-be05-5f7a86268029
Revision:87
Node Kind: directory
Schedule: normal
Last Changed Author: schacon
Last Changed Rev:87
Last Changed Date:2009-05-0216:07:37-0700(Sat,02 May 2009)
$ git merge origin/master
Auto-merging hello.c
Merge made by the 'recursive' strategy.
hello.c |2+-1 file changed,1insertion(+),1deletion(-)
$ git log --oneline --graph --decorate
*0c64627(HEAD, master) Merge remote-tracking branch 'origin/master'|\
|*df85e87(origin/master, origin/branches/default, origin/HEAD, refs/hg/origin/branches/default, refs/hg/origin/bookmarks/master) Add some documentation
*| ba04a2a Update makefile
*| d25d16f Goodbye
|/* ac7955c Create a makefile
*65bb417 Create a standard "hello, world" program
运行测试,然后所有测试都通过了,所以准备将工作共享给团队的其他成员:
$ git push
To hg::/tmp/hello
df85e87..0c64627 master -> master
就是这样,如果现在查看一下 Mercurial 仓库,会发现这样实现了我们所期望的:
$ hg log -G --style compact
o 5[tip]:4,2 dc8fa4f932b8 2014-08-1419:33-0700 ben
|\ Merge remote-tracking branch 'origin/master'||| o 464f27bcefc35 2014-08-1419:27-0700 ben
|| Update makefile
||| o 3:14256fc29598f 2014-08-1419:27-0700 ben
|| Goodbye
||
@ |27db0b4848b3c 2014-08-1419:30-0700 ben
|/ Add some documentation
|
o 182e55d328c8c 2005-08-2601:21-0700 mpm
| Create a makefile
|
o 00a04b987be5a 2005-08-2601:20-0700 mpm
Create a standard "hello, world" program
$ git checkout -b featureA
Switched to a new branch 'featureA'
$ git push origin featureA
To hg::/tmp/hello
*[new branch] featureA -> featureA
这就是所要做的全部,在 Mercurial 这边,它看起来像这样:
$ hg bookmarks
featureA 5:bd5ac26f11f9
$ hg log --style compact -G
@ 6[tip]8f65e5e02793 2014-08-1420:06-0700 ben
| More documentation
|
o 5[featureA]:4,2 bd5ac26f11f9 2014-08-1420:02-0700 ben
|\ Merge remote-tracking branch 'origin/master'||| o 40434aaa6b91f 2014-08-1420:01-0700 ben
|| update makefile
||| o 3:1318914536c86 2014-08-1420:00-0700 ben
|| goodbye
||
o |2 f098c7f45c4f 2014-08-1420:01-0700 ben
|/ Add some documentation
|
o 182e55d328c8c 2005-08-2601:21-0700 mpm
| Create a makefile
|
o 00a04b987be5a 2005-08-2601:20-0700 mpm
Create a standard "hello, world" program
$ hg log --style compact -G
o 10[tip]99611176cbc9 2014-08-1420:21-0700 ben
| A permanent change
|
o 9 f23e12f939c3 2014-08-1420:01-0700 ben
| Add some documentation
|
o 8:1 c16971d33922 2014-08-1420:00-0700 ben
| goodbye
|| o 7:5 a4529d07aad4 2014-08-1420:21-0700 ben
|| A permanent change
|||| @ 68f65e5e02793 2014-08-1420:06-0700 ben
||/ More documentation
||| o 5[featureA]:4,2 bd5ac26f11f9 2014-08-1420:02-0700 ben
||\ Merge remote-tracking branch 'origin/master'||||| o 40434aaa6b91f 2014-08-1420:01-0700 ben
||| update makefile
|||+---o 3:1318914536c86 2014-08-1420:00-0700 ben
|| goodbye
||| o 2 f098c7f45c4f 2014-08-1420:01-0700 ben
|/ Add some documentation
|
o 182e55d328c8c 2005-08-2601:21-0700 mpm
| Create a makefile
|
o 00a04b987be5a 2005-08-2601:20-0700 mpm
Create a standard "hello, world" program
Among the DVCS, another famous one is Bazaar. Bazaar is free and open source, and is part of the GNU Project. It behaves very differently from Git. Sometimes, to do the same thing as with Git, you have to use a different keyword, and some keywords that are common don’t have the same meaning. In particular, the branch management is very different and may cause confusion, especially when someone comes from Git’s universe. Nevertheless, it is possible to work on a Bazaar repository from a Git one.
There are many projects that allow you to use Git as a Bazaar client. Here we’ll use Felipe Contreras’ project that you may find at https://github.com/felipec/git-remote-bzr. To install it, you just have to download the file git-remote-bzr in a folder contained in your $PATH:
You also need to have Bazaar installed. That’s all!
① Create a Git repository from a Bazaar repository
It is simple to use. It is enough to clone a Bazaar repository prefixing it by bzr::. Since Git and Bazaar both do full clones to your machine, it’s possible to attach a Git clone to your local Bazaar clone, but it isn’t recommended. It’s much easier to attach your Git clone directly to the same place your Bazaar clone is attached to ‒ the central repository.
Let’s suppose that you worked with a remote repository which is at address bzr+ssh://developer@mybazaarserver:myproject. Then you must clone it in the following way:
$ git clone bzr::bzr+ssh://developer@mybazaarserver:myproject myProject-Git
$ cd myProject-Git
At this point, your Git repository is created but it is not compacted for optimal disk use. That’s why you should also clean and compact your Git repository, especially if it is a big one:
$ git gc --aggressive
② Bazaar branches
Bazaar only allows you to clone branches, but a repository may contain several branches, and git-remote-bzr can clone both. For example, to clone a branch:
The second command clones all the branches contained in the emacs repository; nevertheless, it is possible to point out some branches:
$ git config remote-bzr.branches 'trunk, xwindow'
Some remote repositories don’t allow you to list their branches, in which case you have to manually specify them, and even though you could specify the configuration in the cloning command, you may find this easier:
Since you are working on a project managed with Bazaar, you shouldn’t create a .gitignore file because you may accidentally set it under version control and the other people working with Bazaar would be disturbed. The solution is to create the .git/info/exclude file either as a symbolic link or as a regular file. We’ll see later on how to solve this question.
Bazaar uses the same model as Git to ignore files, but also has two features which don’t have an equivalent into Git. The complete description may be found in the documentation. The two features are:
“!!” allows you to ignore certain file patterns even if they’re specified using a “!” rule.
“RE:” at the beginning of a line allows you to specify a Python regular expression (Git only allows shell globs).
As a consequence, there are two different situations to consider:
If the .bzrignore file does not contain any of these two specific prefixes, then you can simply make a symbolic link to it in the repository: ln -s .bzrignore .git/info/exclude
Otherwise, you must create the .git/info/exclude file and adapt it to ignore exactly the same files in .bzrignore.
Whatever the case is, you will have to remain vigilant against any change of .bzrignore to make sure that the .git/info/exclude file always reflects .bzrignore. Indeed, if the .bzrignore file were to change and contained one or more lines starting with “!!” or “RE:”, Git not being able to interpret these lines, you’ll have to adapt your .git/info/exclude file to ignore the same files as the ones ignored with .bzrignore. Moreover, if the .git/info/exclude file was a symbolic link, you’ll have to first delete the symbolic link, copy .bzrignore to .git/info/exclude and then adapt the latter. However, be careful with its creation because with Git it is impossible to re-include a file if a parent directory of that file is excluded.
④ Fetch the changes of the remote repository
To fetch the changes of the remote, you pull changes as usually, using Git commands. Supposing that your changes are on the master branch, you merge or rebase your work on the origin/master branch:
$ git pull --rebase origin
⑤ Push your work on the remote repository
Because Bazaar also has the concept of merge commits, there will be no problem if you push a merge commit. So you can work on a branch, merge the changes into master and push your work. Then, you create your branches, you test and commit your work as usual. You finally push your work to the Bazaar repository:
$ git push origin master
⑥ Caveats
Git’s remote-helpers framework has some limitations that apply. In particular, these commands don’t work:
git push origin :branch-to-delete (Bazaar can’t accept ref deletions in this way.)
git push origin old:new (it will push old)
git push --dry-run origin branch (it will push)
⑦ Summary
Since Git’s and Bazaar’s models are similar, there isn’t a lot of resistance when working across the boundary. As long as you watch out for the limitations, and are always aware that the remote repository isn’t natively Git, you’ll be fine.
john john@example.com "John Doe"
john johnny@appleseed.net "John Doe"
bob employeeX@example.com "Anon X. Mouse"
joe employeeY@example.com "Anon Y. Mouse"
# ...
$ git log --oneline --decorate --graph --all
*cfd46ab(HEAD, master) Add documentation for new feature
* a730d77 Whitespace
*d254865(origin/master, origin/HEAD) Upgrade to latest metrowerks on Beos -- the Intel one.* bd2f54a Put in fix for jam's NT handle leak.[...]
我们有两个新提交,现在检查下是否有其他人在工作:
$ git fetch
remote: Counting objects:5, done.
remote: Compressing objects:100%(3/3), done.
remote: Total 3(delta 2), reused 0(delta 0)
Unpacking objects:100%(3/3), done.
From https://10.0.1.254/Jam
d254865..6afeb15 master -> origin/master
$ git log --oneline --decorate --graph --all
*6afeb15(origin/master, origin/HEAD) Update copyright
|*cfd46ab(HEAD, master) Add documentation for new feature
|* a730d77 Whitespace
|/* d254865 Upgrade to latest metrowerks on Beos -- the Intel one.* bd2f54a Put in fix for jam's NT handle leak.[...]
$ git p4 clone //depot/www/live www-shallow
Importing from //depot/www/live into www-shallow
Initialized empty Git repository in /private/tmp/www-shallow/.git/
Doing initial import of //depot/www/live/ from revision #head into refs/remotes/p4/master
$ cd myproject
$ git log --oneline --all --graph --decorate
*70eaf78(HEAD, p4/master, p4/HEAD, master) Initial import of //depot/www/live/ from the state at revision #head
$ git log --oneline --all --graph --decorate
*018467c(HEAD, master) Change page title
* c0fb617 Update link
*70eaf78(p4/master, p4/HEAD) Initial import of //depot/www/live/ from the state at revision #head
$ git p4 rebase
Performing incremental import into refs/remotes/p4/master git branch
Depot paths://depot/www/live/
No changes to import!
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
Applying: Update link
Applying: Change page title
index.html |2+-1 file changed,1insertion(+),1deletion(-)
从输出中可能大概得知,git p4 rebase 是 git p4 sync 接着 git rebase p4/master 的快捷方式,它比那更聪明一些,特别是工作在多个分支时,但这是一个进步。
#A Perforce Change Specification.
#
#Change: The change number.'new'on a new changelist.#Date: The date this specification was last modified.#Client: The client on which the changelist was created. Read-only.#User: The user who created the changelist.#Status: Either 'pending'or 'submitted'. Read-only.#Type: Either 'public'or 'restricted'. Default is 'public'.#Description: Comments about the changelist. Required.#Jobs: What opened jobs are to be closed by this changelist.#You may delete jobs from this list.(New changelists only.)#Files: What opened files from the default changelist are to be added#tothis changelist. You may delete files from this list.
# (New changelists only.)
Change: new
Client: john_bens-mbp_8487
User: john
Status: new
Description:
Update link
Files://depot/www/live/index.html # edit
######## git author ben@straub.cc does not match your p4 account.
######## Use option --preserve-user to modify authorship.
######## Variable git-p4.skipUserNameCheck hides this message.
######## everything below this line is just the diff #######
---//depot/www/live/index.html 2014-08-31 18:26:05.000000000 0000+++/Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/index.html 2014-08-3118:26:05.0000000000000
@@ -60,7+60,7 @@
</td><td valign=top>
Source and documentation for-<a href="http://www.perforce.com/jam/jam.html">+<a href="jam.html">
Jam/MR</a>,
a software build tool.</td>
$ git p4 submit
Perforce checkout for depot path //depot/www/live/ located at /Users/ben/john_bens-mbp_8487/john_bens-mbp_8487/depot/www/live/
Synchronizing p4 checkout......-file(s) up-to-date.
Applying dbac45b Update link
//depot/www/live/index.html#4 - opened for edit
Change 12143 created with 1 open file(s).
Submitting change 12143.
Locking 1 files ...
edit //depot/www/live/index.html#5
Change 12143 submitted.
Applying 905ec6a Change page title
//depot/www/live/index.html#5 - opened for edit
Change 12144 created with 1 open file(s).
Submitting change 12144.
Locking 1 files ...
edit //depot/www/live/index.html#6
Change 12144 submitted.
All commits applied!
Performing incremental import into refs/remotes/p4/master git branch
Depot paths://depot/www/live/
Import destination: refs/remotes/p4/master
Importing revision 12144(100%)
Rebasing the current branch onto remotes/p4/master
First, rewinding head to replay your work on top of it...
$ git log --oneline --all --graph --decorate
*775a46f(HEAD, p4/master, p4/HEAD, master) Change page title
*05f1ade Update link
*75cd059 Update copyright
*70eaf78 Initial import of //depot/www/live/ from the state at revision #head
$ git log -1
commit 775a46f630d8b46535fc9983cf3ebe6b9aa53145
Author: John Doe <john@example.com>
Date: Sun Aug 3110:31:442014-0800
Change page title
[git-p4: depot-paths ="//depot/www/live/": change =12144]
当尝试提交一次合并提交时会发生什么? 让我们来尝试一下,这是可能会遇到的一种情形:
$ git log --oneline --all --graph --decorate
*3be6fd8(HEAD, master) Correct email address
*1dcbf21 Merge remote-tracking branch 'p4/master'|\
|*c4689fc(p4/master, p4/HEAD) Grammar fix
*| cbacd0a Table borders: yes please
*| b4959b6 Trademark
|/*775a46f Change page title
*05f1ade Update link
*75cd059 Update copyright
*70eaf78 Initial import of //depot/www/live/ from the state at revision #head
Git 在 Windows 开发者当中变得流行起来,如果我们正在 Windows 上编写代码并且正在使用 Microsoft 的 Team Foundation Server (TFS),这会是个好机会,TFS 是一个包含工作项目检测与跟踪、支持 Scrum 与其他流程管理方法、代码审核、版本控制的协作套件。这里有一点困惑:TFS 是服务器,它支持通过 Git 与它们自定义的 VCS 来管理源代码,这被他们称为 TFVC(Team Foundation Version Control)。Git 支持 TFS(自 2013 版本起)的部分新功能,所以在那之前所有工具都将版本控制部分称为 “TFS”,即使实际上他们大部分时间都在与 TFVC 工作。
$ git rebase FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: update readme
Applying: update code
$ git log --oneline --graph --decorate --all
*5a0e25e(HEAD, master) update code
*6eb3eb5 update readme
*8ef06a8(tag: TFS_C35320, origin_tfs/tfs) just some text
*d44b17a(tag: TFS_C35190) Goodbye
*126aa7b(tag: TFS_C35189)*8f77431(tag: TFS_C35178) FIRST
*0745a25(tag: TFS_C35177) Created team project folder $/tfvctest via the \
Team Project Creation Wizard
$ git tf checkin -m 'Updating readme and code'
Username: domain\user
Password:
Connecting to TFS...
Checking in to $/myproject:100%, done.
Checked commit 5a0e25e in as changeset 35348
$ git log --oneline --graph --decorate --all
*5a0e25e(HEAD, tag: TFS_C35348, origin_tfs/tfs, master) update code
*6eb3eb5 update readme
*8ef06a8(tag: TFS_C35320) just some text
*d44b17a(tag: TFS_C35190) Goodbye
*126aa7b(tag: TFS_C35189)*8f77431(tag: TFS_C35178) FIRST
*0745a25(tag: TFS_C35177) Created team project folder $/tfvctest via the \
Team Project Creation Wizard