5分钟学会git (svn基础)
git是核心,cogito是它的一个包装,可以使得git更容易使用。和SVN的常用命令对照
The Cogito commands are in the form cg command, the Git commands take t
he form of git command. In both cases, you can interchangeably use the c
g-command and git-command form as well.
Cogito can produce colourful output with some commands; since some peop
le hate colors way more than the rest likes them, by default the colors
are turned off. If you would like to have colors in your output, create
~/.cgrc and put this inside:
cg-diff -c
cg-help -c
cg-log -c
The format and purpose is the same as of the ~/.svnrc file; you can add
other commands and switches there later if you wish (my tip is -f for c
g-log).
Also, you may find it convenient to watch your repository using the git
k repository as you go.
Your Very Own
For the first introduction, let's make your project tracked by Git and
see how we get around to do daily development in it. Let's cd to the dir
ectory with your project and initialize a brand new Git repository with
it:
cg init svnadmin create repo
svn import file://repo
cg init will both initialize the repository and create the initial impo
rt, given that repositories are coupled with working copies.
Now your tree is officially tracked by Git. You can explore the .git su
bdirectory a bit if you want, or don't if you don't care. Do some random
changes to your tree now - poke into few files or such. Let's check wha
t we've done:
cg diff svn diff | less
That's it. This is one of the more powerful commands; just like with SV
N, you can pass -rs, limit the diff to specific directories or files and
so on. Git embeds special information in the diffs about adds, removals
and mode changes:
cg patch patch -p0
That will apply the patch while telling Git about and performing those
"meta-changes".
There is a more conscise changes representation available:
cg status svn status
This will show the conscise changes summary as well as list any files t
hat you haven't either ignored or told Git about. In addition, it will a
lso show some cryptic line at the top (with "master" inside) - ignore it
for now, we'll learn more about it later.
While we are at the status command, over time plenty of the "? lines" w
ill get in there, denoting files not tracked by Git. Wait a moment if yo
u want to add them, run cg clean if you want to get rid all of them, or
add them to the .gitignore file if you want to keep them around untracke
d (works the same as .svnignore).
Somewhat out of order, one thing svn update would do is restoring files
you've accidentally removed. The command for that in Cogito is cg resto
re; you can restore everything, just specified files, force it to overwr
ite missing files.
So, just like in SVN, you need to tell Git when you add, move or remove
any files:
cg add file
cg rm -f file
cg mv filesvn add file
svn rm file
svn mv file
Cogito is more promising than SVN here; especially, you can keep files
that are yet present in the working directory (cg rm can remove them for
you if you pass it the -f switch) - saves a lot of annoyance when remov
ing files matching to a wildcard. You can also recursively add/remove wh
ole directories and so on; Cogito's cool!
So, it's about time we committed our changes. Big surprise about the co
mmand:
cg commit svn commit
As with Subversion, you can limit the commit only to specified files an
d so on. Few words on the commit message: it is customary to have a shor
t commit summary as the first line of the message, because various tools
listing commits frequently show only the first line of the message You
can specify the commit message using the -m parameter as you are used, b
ut there're two differences - the text gets autoformatted to paragraphs
and you can pass several -m arguments and they will create separate para
graphs in the commit message:
cg commit -m"Short one-line description" -m"And here can come \
your longer description of the commit, and it gets split out \
and reflown to wrapped paragraphs just right."
If you don't pass any -m parameter or pass the -e parameter, your favor
ite $EDITOR will get run and you can compose your commit message there,
just as with Subversion. In addition, the list of files to be committed
is shown and you can actually delete lines with the files you don't want
to commit and they won't be. You can also adjust the authorship informa
tion in the editor.
And as a bonus, if you pass it the -p parameter it will show the whole
patch being committed in the editor so that you can do a quick last-time
review. And you can manually modify the patch and your changes will get
propagated to the commit (and your working tree).
By the way, if you screwed up committing, there's not much you can do w
ith Subversion, except using some enigmatic svnadmin subcommands. Git do
es better - you can amend your latest commit (re-edit the metadata as we
ll as update the tree) using cg commit --amend, or toss your latest comm
it away completely using cg admin-uncommit.
Now that we have committed some stuff, you might want to review your hi
story:
cg log
cg seek rev
git blame filesvn log | less
svn checkout -r tag
svn blame file
The log command works quite similar in SVN and Git; again, cg log is qu
ite powerful, please look through its options to see some of the stuff i
t can do.
To move your tree to some older revision, use the seek command (and pas
s it no arguments to go back to your latest revision_. Note that this is
only for "temporary excursions" - if you want to just reset your histor
y and make a given commit your new head, think again and if you are sure
, cg switch -f -r newrev master (this will be perhaps made simpler in th
e future, we will review the switch command in more detail in the future
).
Git now has an annotation command akin to Subversion's, but there are b
ig chances that you probably want to do something different! Usually, wh
en using annotate you are looking for the origin of some piece of code,
and the so-called pickaxe of Git is much more comfortable tool for that
job (detailed discussion; you may want to use cg log -S string instead o
f git log -Sstring, tho').
Tagging and branching
Subversion marks certain checkpoints in history through copies, the cop
y is usually placed in a directory named tags. Git tags are quite more p
owerful. The Git tag can have an arbitrary description attached (the fir
st line is special as in the commit case), some people actually store th
e whole release announcements in the tag descriptions. The identity of t
he person who tagged is stored (again following the same rules as identi
ty of the committer). You usually tag commits but if you want, you can t
ag files (or trees, but that's a bit lowlevel) as well. And the tag can
be cryptographically PGP signed to verify the identity (by Git's nature
of working, that signature also confirms the validity of the associated
revision, its history and tree). So, let's do it:
cg tag name svn copy http://example.com/svn/trunk http://example.com/sv
n/tags/name
To list tags in Subversion, you could run svn list http://example.com/s
vn/tags. In Git, you can find out using cg tag-ls and show details (auth
or, description, PGP signature verification, ...) using cg tag-show.
Like Subversion, Git can do branches (surprise surprise!). In Subversio
n, you basically copy your project to a subdirectory. In Git, you tell i
t, well, to create a branch.
cg switch -c branch
cg switch branch svn copy http://example.com/svn/trunk http://example.c
om/svn/branches/branch
svn switch http://example.com/svn/branches/branch
The first command creates a branch, the second command switches your tr
ee to a certain branch. You can pass an -r argument to switch to base yo
ur new branch on a different revision than the latest one.
You can list your branches conveniently using the aforementioned cg-sta
tus command - the cryptic listing at the top is just the listing of bran
ches. The current one is denoted by an "arrow".
Git supports merging between branches much better than Subversion - his
tory of both branches is preserved over the merges and repeated merges o
f the same branches are supported out-of-the-box. Make sure you are on o
ne of the to-be-merged branches and merge the other one now:
cg merge branch (assuming the branch was created in revision 20 and you
are inside a working copy of trunk)
svn merge -r 20:HEAD http://example.com/svn/branches/branch
If changes were made on only one of the branches since the last merge,
they are simply replayed on your other branch (so-called fast-forward me
rge). If changes were made on both branches, they are merged intelligent
ly (so-called three-way merge): if any changes conflicted, cg merge will
report them and let you resolve them, updating the rest of the tree alr
eady to the result state; you can cg commit when you resolve the conflic
ts. If no changes conflicted, cg commit is invoked automatically, lettin
g you edit the commit message (or you can do cg merge -n branch to revie
w the merge result and then do the commit yourself).
Sometimes, you do want to throw away the history of one of the branches
, e.g. when you did a fine-tracked development of a topic and now want t
o squash it to a single conceptual change commit - just pass merge the -
-squash switch. Also, sometimes you may want to join together two unrela
ted branches (coming from different projects; hold on, we'll get to that
in a minute): -j will take care of that.
Aside of merging, sometimes you want to just pick one commit from a dif
ferent branch. We have already mentioned the command cg patch. It can ap
ply patches, but also autocommit them and extract them from given commit
s. cg patch -C rev combines both functionality and will cherry pick a gi
ven commit to your branch.
Going Remote
So far, we have neglected that Git is a distributed version control sys
tem. It is time for us to set the record straight - let's grab some stuf
f from remote sites.
If you are working on someone else's project, you usually want to clone
its repository instead of starting your own. We've already mentioned th
at at the top of this document:
cg clone url svn checkout url
Now you have got your master branch as when initializing a new reposito
ry, but in addition you got an origin remote branch. Remote branch, you
ask? Well, so far we have worked only with local branches. Remote branch
es are a mirror image of branches in remote repositories and you don't e
ver switch to them directly or write to them. Let me repeat - you never
mess with remote branches. If you want to switch to a remote branch, you
need to create a corresponding local branch which will "track" the remo
te branch. In clone's default setup, the master local branch tracks the
origin remote branch, which represents the remote repository.
You can add more remote branches, to a cloned repository as well as jus
t an initialized one, using cg branch-add branch url. cg branch-ls lists
all the branches.
Now, how to get any new changes from a remote repository to your local
branch? You fetch them: cg fetch branch. At this point they are in your
local branch and you can examine them using cg log -r branch (cg log -r
HEAD..branch to see just the changes you don't have in your branch), dif
f them, and obviously, merge them - just do cg merge branch. Note that i
f you don't specify a branch for fetch or merge, it will conveniently de
fault to origin.
Since you frequently just fetch + merge, there is a command to automate
that:
cg update branch svn update
Again, it will default to origin if no branch was specified. It is reco
mmended to use update instead of fetch + merge since it does the first t
hing even if the remote branch' history got altered (which is also a rea
son why altering history is discouraged at the moment you publish it).
So we can get updates from the remote side (pull changes). Can we do th
e opposite as well? Push our changes? Yes! We do cg push branch which wi
ll push our current branch to the given remote branch - note that this w
orks generally only over SSH (or HTTP but with special webserver setup).
It is highly recommended to setup a SSH key and an SSH agent mechanism
so that you don't have to type in a password all the time.
One important thing is that you should push only to remote branches tha
t are not currently checked out on the other side (for the same reasons
you never switch to a remote branch locally)! Otherwise the working copy
at the remote branch will get out of date and confusion will ensue. The
best way to avoid that is to push only to remote repositories with no w
orking copy at all - so called bare repositories which are commonly used
for public access or developers' meeting point - just for exchange of h
istory where a checked out copy would be a waste of space anyway. You ca
n create such a repository using cg admin-setuprepo path - you can add a
dditional options to make it shared for a UNIX group of users.
Git can work with the same workflow as Subversion, with a group of deve
lopers using a single repository for exchange of their work - the only c
hange is that their changes aren't submitted automatically but they have
to push (however, you can setup a post-commit hook that will push for y
ou every time you commit; that loses the flexibility to fix up a screwed
commit, though). The developers have to have either an entry in htacces
s (for HTTP DAV) or a UNIX account (for SSH) - you can restrict their sh
ell account only to Git pushing/fetching by using the git-shell login sh
ell.
You can also exchange patches by mail. Git has very good support for pa
tches incoming by mail. You can apply them by feeding mailboxes with pat
ch mails to cg patch -m. If you want to send patches (or a third-party c
hanges to an upstream repository with no commit access in general), it i
s best to use the StGIT tool - see the StGIT Crash Course).
If you have any question or problem which is not obvious from the docum
entation, please contact us at the Git mailing list at [email protected]
rg. We hope you enjoy using Git and Cogito!
--
I come from the past to save the future~~~
[m
页:
[1]