用git搭建一个小的远程仓库

建立远程仓库

  1. git init 初始化
  2. git remote add origin ssh://root@ip/~/testgit/.git 建立远程仓库
  3. git push origin master 将本地仓库跟踪到git仓库

远程拉取代码

  1. git clone ssh://root@ip/~/testgit/.git 输入root的密码,也可以用其他有访问权限的用户
  2. 以上就可以拉去远程的代码了,不过不能推送
  3. 若果要推送,需要设置 远程仓库 git config receive.denyCurrentBranch=warn/ignore ,这样就可以远程推送了
发表在 git | 标签为

git:HTTPS和SSH方式的区别和使用

[摘要:正在治理Git项目上,良多时间皆是间接应用https url克隆到当地,固然也有有些人应用SSH url克隆到当地。那两种体式格局的首要差别正在于:应用https url克隆对初教者来讲会比拟轻易,复造https]

在管理Git项目上,很多时候都是直接使用https url克隆到本地,当然也有有些人使用SSH url克隆到本地。这两种方式的主要区别在于:使用https url克隆对初学者来说会比较方便,复制https url然后到git Bash里面直接用clone命令克隆到本地就好了,但是每次fetch和push代码都需要输入账号和密码,这也是https方式的麻烦之处。而使用SSH url克隆却需要在克隆之前先配置和添加好SSH key,因此,如果你想要使用SSH url克隆的话,你必须是这个项目的拥有者。否则你是无法添加SSH key的,另外ssh默认是每次fetch和push代码都不需要输入账号和密码,如果你想要每次都输入账号密码才能进行fetch和push也可以另外进行设置。前面的几篇介绍Git的博客里面采用的都是https的方式作为案例,今天主要是记录如何配置使用ssh方式来提交和克隆代码。

步骤1:检查你的电脑上是否已经生成了SSH Key
在git bash下执行如下命令

cd  ~/.ssh ls

这两个命令就是检查是否已经存在id_rsa.pub或id_dsa.pub文件,如果文件已经存在,那么你可以跳过步骤2,直接进入步骤3。

步骤2:创建一个SSH Key
在git bash下执行如下命令

ssh-keygen -t rsa -C "你的email地址"

代码参数含义:
-t指定密钥类型,默认是rsa,可以省略。
-C设置注释文字,比如邮箱。
-f指定密钥文件存储文件名。
以上命令省略了-f参数,因此,运行上面那条命令后会让你输入一个文件名,用于保存刚才生成的SSH key代码,如:
Generating public/private rsa key pair.
Enter file in which to save the key (/c/Users/you/.ssh/id_rsa): [Press enter]
当然,你也可以不输入文件名,使用默认文件名(推荐),那么就会生成id_rsa和id_rsa.pub两个秘钥文件。
接着又会提示你输入两次密码(该密码是你push文件的时候要输入的密码,而不是github管理者的密码),当然,你也可以不输入密码,直接按回车。那么push的时候就不需要输入密码,直接提交到Git服务器上了,如:
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
接下来,就会显示如下一些提示,如:
Your identification has been saved in /c/Users/you/.ssh/id_rsa.
Your public key has been saved in /c/Users/you/.ssh/id_rsa.pub.
The key fingerprint is:
01:0f:f4:3b:ca:85:d6:17:a1:7d:f0:68:9d:f0:a2:db 你的email地址
当你在Git Bash上看到这段显示的时候,那就说明,你的SSH key已经创建成功,你只需要添加到Git服务器上的SSH key上就可以了。

步骤3:添加SSH Key到Git服务器
这个由于不同的Git服务器,在界面添加的区域不一样,所以不做详述,具体参照不同Git服务器自己的操作。
经历了以上的三个步骤之后,你就可以愉快的使用SSH URL的方式来提交和克隆项目的代码了,并且不需要再频繁的输入账号密码,如果你之前已经一直使用https方式进行开发,当前想要切换成为ssh方式进行开发,只需要执行如下几步的操作即可:

git remote rm origin git remote add origin "Git仓库的ssh格式地址" git push origin

git reset 用法简介

在git的一般使用中,如果发现错误的将不想staging的文件add进入index之后,想回退取消,则可以使用命令:git reset HEAD <file>…,同时git add完毕之后,git也会做相应的提示,比如:
引用
# Changes to be committed: 
#   (use “git reset HEAD <file>…” to unstage) 
# new file:   Test.scala 
git reset [–hard|soft|mixed|merge|keep] [<commit>或HEAD]:将当前的分支重设(reset)到指定的<commit>或者HEAD(默认,如果不显示指定commit,默认是HEAD,即最新的一次提交),并且根据[mode]有可能更新index和working directory。mode的取值可以是hard、soft、mixed、merged、keep。下面来详细说明每种模式的意义和效果。
A). –hard:重设(reset) index和working directory,自从<commit>以来在working directory中的任何改变都被丢弃,并把HEAD指向<commit>。
具体一个例子,假设有三个commit, git st:
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c
执行git reset –hard HEAD~1后,
显示:HEAD is now at commit2,运行git log
commit2: add test2.c
commit1: add test1.c
运行git st, 没有任何变化
B). –soft:index和working directory中的内容不作任何改变,仅仅把HEAD指向<commit>。这个模式的效果是,执行完毕后,自从<commit>以来的所有改变都会显示在git status的”Changes to be committed”中。
具体一个例子,假设有三个commit, git st:
commit3: add test3.c
commit2: add test2.c
commit1: add test1.c
执行git reset –soft(默认) HEAD~1后,运行git log
commit2: add test2.c
commit1: add test1.c
运行git status, 则test3.c处于暂存区,处于准备提交状态。即此时git commit就会提交它。
  在使用git进行协作开发时,我们经常需要将自己的修改生成patch发给被人,但是在修改代码的过程中我们进行了很多次的提交,如何生成从最初的代码状态到最终代码状态的patch呢?下面要介绍的功能是应对这中情况。
现假设我们git软件仓库中的分支情况如下:
a–>b–>c
也就是说我们的代码从状态a修改到状态b,进行一次提交,然后再修改到状态c,进行一次提交。这时我们已经肯定由a到c的修改是正确的,不再需要状态b了,并且要把从a到c的变化生成一个patch发送给别人。如果直接打包的话会生成两个path,那么如何生成一个patch呢,这时就需要git-reset命令。
首先给状态a创建一个tag,假设名称为A,然后执行
git-reset –soft A
这样我们的软件仓库就变为
a
状态b和状态c都已经被删除了,但是当前的代码并没有被改变,还是状态c的代码,这时我们做一次提交,软件仓库变成下面的样子:
a–>d
状态d和状态c所对应的代码是完全相同的,只是名字不同。现在就可以生成一个patch打包发给别人了
C). –mixed:仅reset index,但是不reset working directory。这个模式是默认模式,即当不显示告知git reset模式时,会使用mixed模式。这个模式的效果是,working directory中文件的修改都会被保留,不会丢弃,但是也不会被标记成”Changes to be committed”,但是会打出什么还未被更新的报告。报告如下:
引用
Unstaged changes after reset:
M Test.Scala
M test.txt
D). –merge和–keep用的不多,在下面的例子中说明。
二、常用示例
下面列出一些git reset的典型的应用场景:
A) 回滚add操纵
引用
$ edit                                     (1)
$ git add frotz.c filfre.c
$ mailx                                    (2)
$ git reset                                (3)
$ git pull git://info.example.com/ nitfol  (4)
(1) 编辑文件frotz.c, filfre.c,做了些更改,并把更改添加到了index
(2) 查看邮件,发现某人要你pull,有一些改变需要你merge下来
(3) 然而,你已经把index搞乱了,因为index同HEAD commit不匹配了,但是你知道,即将pull的东西不会影响已经修改的frotz.c和filfre.c,因此你可以revert这两个文件的改变。revert后,那些改变应该依旧在working directory中,因此执行git reset。
(4) 然后,执行了pull之后,自动merge,frotz.c和filfre.c这些改变依然在working directory中。
B) 回滚最近一次commit
引用
$ git commit …
$ git reset –soft HEAD^      (1)
$ edit                        (2)
$ git commit -a -c ORIG_HEAD  (3)
(1) 当提交了之后,你又发现代码没有提交完整,或者你想重新编辑一下提交的comment,执行git reset –soft HEAD^,让working tree还跟reset之前一样,不作任何改变。
HEAD^指向HEAD之前最近的一次commit。
(2) 对working tree下的文件做修改
(3) 然后使用reset之前那次commit的注释、作者、日期等信息重新提交。注意,当执行git reset命令时,git会把老的HEAD拷贝到文件.git/ORIG_HEAD中,在命令中可以使用ORIG_HEAD引用这个commit。commit 命令中 -a 参数的意思是告诉git,自动把所有修改的和删除的文件都放进stage area,未被git跟踪的新建的文件不受影响。commit命令中-c <commit> 或者 -C <commit>意思是拿已经提交的commit对象中的信息(作者,提交者,注释,时间戳等)提交,那么这条commit命令的意思就非常清晰了,把所有更改的文件加入stage area,并使用上次的提交信息重新提交。
C) 回滚最近几次commit,并把这几次commit放到叫做topic的branch上去。
引用
$ git branch topic/wip     (1)
$ git reset –hard HEAD~3  (2)
$ git checkout topic/wip   (3)
(1) 你已经提交了一些commit,但是此时发现这些commit还不够成熟,不能进入master分支,但你希望在新的branch上润色这些commit改动。因此执行了git branch命令在当前的HEAD上建立了新的叫做 topic/wip的分支。
(2) 然后回滚master branch上的最近三次提交。HEAD~3指向当前HEAD-3个commit的commit,git reset –hard HEAD~3即删除最近的三个commit(删除HEAD, HEAD^, HEAD~2),将HEAD指向HEAD~3。
D) 永久删除最后几个commit
引用
$ git commit …
$ git reset –hard HEAD~3   (1)
(1) 最后三个commit(即HEAD, HEAD^和HEAD~2)提交有问题,你想永久删除这三个commit。
E) 回滚merge和pull操作
引用
$ git pull                         (1)
Auto-merging nitfol
CONFLICT (content): Merge conflict in nitfol
Automatic merge failed; fix conflicts and then commit the result.
$ git reset –hard                 (2)
$ git pull . topic/branch          (3)
Updating from 41223… to 13134…
Fast-forward
$ git reset –hard ORIG_HEAD       (4)
(1) 从origin拉下来一些更新,但是产生了很多冲突,你暂时没有这么多时间去解决这些冲突,因此你决定稍候有空的时候再重新pull。
(2) 由于pull操作产生了冲突,因此所有pull下来的改变尚未提交,仍然再stage area中,这种情况下git reset –hard 与 git reset –hard HEAD意思相同,即都是清除index和working tree中被搞乱的东西。
(3) 将topic/branch合并到当前的branch,这次没有产生冲突,并且合并后的更改自动提交。
(4) 但是此时你又发现将topic/branch合并过来为时尚早,因此决定退滚merge,执行git reset –hard ORIG_HEAD回滚刚才的pull/merge操作。说明:前面讲过,执行git reset时,git会把reset之前的HEAD放入.git/ORIG_HEAD文件中,命令行中使用ORIG_HEAD引用这个commit。同样的,执行pull和merge操作时,git都会把执行操作前的HEAD放入ORIG_HEAD中,以防回滚操作。
F) 在被污染的working tree中回滚merge或者pull
引用
$ git pull                         (1)
Auto-merging nitfol
Merge made by recursive.
nitfol                |   20 +++++—-
$ git reset –merge ORIG_HEAD      (2)
(1) 即便你已经在本地更改了一些你的working tree,你也可安全的git pull,前提是你知道将要pull的内容不会覆盖你的working tree中的内容。
(2) git pull完后,你发现这次pull下来的修改不满意,想要回滚到pull之前的状态,从前面的介绍知道,我们可以执行git reset –hard ORIG_HEAD,但是这个命令有个副作用就是清空你的working tree,即丢弃你的本地未add的那些改变。为了避免丢弃working tree中的内容,可以使用git reset –merge ORIG_HEAD,注意其中的–hard 换成了 –merge,这样就可以避免在回滚时清除working tree。
G) 被中断的工作流程
在实际开发中经常出现这样的情形:你正在开发一个大的feature,此时来了一个紧急的bug需要修复,但是目前在working tree中的内容还没有成型,还不足以commit,但是你又必须切换的另外的branch去fix bug。请看下面的例子
引用
$ git checkout feature ;# you were working in “feature” branch and
$ work work work       ;# got interrupted
$ git commit -a -m “snapshot WIP”                 (1)
$ git checkout master
$ fix fix fix
$ git commit ;# commit with real log
$ git checkout feature
$ git reset –soft HEAD^ ;# go back to WIP state  (2)
$ git reset                                       (3)
(1) 这次属于临时提交,因此随便添加一个临时注释即可。
(2) 这次reset删除了WIP commit,并且把working tree设置成提交WIP快照之前的状态。
(3) 此时,在index中依然遗留着“snapshot WIP”提交时所做的uncommit changes,git reset将会清理index成为尚未提交”snapshot WIP”时的状态便于接下来继续工作。
(H) Reset单独的一个文件
假设你已经添加了一个文件进入index,但是而后又不打算把这个文件提交,此时可以使用git reset把这个文件从index中去除。
引用
$ git reset — frotz.c                      (1)
$ git commit -m “Commit files in index”     (2)
$ git add frotz.c                           (3)
(1) 把文件frotz.c从index中去除,
(2) 把index中的文件提交
(3) 再次把frotz.c加入index
(I) 保留working tree并丢弃一些之前的commit
假设你正在编辑一些文件,并且已经提交,接着继续工作,但是现在你发现当前在working tree中的内容应该属于另一个branch,与这之前的commit没有什么关系。此时,你可以开启一个新的branch,并且保留着working tree中的内容。
引用
$ git tag start
$ git checkout -b branch1
$ edit
$ git commit …                            (1)
$ edit
$ git checkout -b branch2                   (2)
$ git reset –keep start                    (3)
(1) 这次是把在branch1中的改变提交了。
(2) 此时发现,之前的提交不属于这个branch,此时你新建了branch2,并切换到了branch2上。
(3) 此时你可以用reset –keep把在start之后的commit清除掉,但是保持working tree不变。

 

git tag — 标签相关操作

标签可以针对某一时间点的版本做标记,常用于版本发布。

  • 列出标签

$ git tag # 在控制台打印出当前仓库的所有标签
$ git tag -l ‘v0.1.*’ # 搜索符合模式的标签

  • 打标签

git标签分为两种类型:轻量标签和附注标签。轻量标签是指向提交对象的引用,附注标签则是仓库中的一个独立对象。建议使用附注标签。
# 创建轻量标签
$ git tag v0.1.2-light

# 创建附注标签
$ git tag -a v0.1.2 -m “0.1.2版本”

创建轻量标签不需要传递参数,直接指定标签名称即可。
创建附注标签时,参数a即annotated的缩写,指定标签类型,后附标签名。参数m指定标签说明,说明信息会保存在标签对象中。

  • 切换到标签

与切换分支命令相同,用git checkout [tagname]
查看标签信息
git show命令可以查看标签的版本信息:
$ git show v0.1.2

  • 删除标签

误打或需要修改标签时,需要先将标签删除,再打新标签。
$ git tag -d v0.1.2 # 删除标签

参数d即delete的缩写,意为删除其后指定的标签。

  • 给指定的commit打标签

打标签不必要在head之上,也可在之前的版本上打,这需要你知道某个提交对象的校验和(通过git log获取)。
# 补打标签
$ git tag -a v0.1.1 9fbc3d0

  • 标签发布

通常的git push不会将标签对象提交到git服务器,我们需要进行显式的操作:
$ git push origin v0.1.2 # 将v0.1.2标签提交到git服务器
$ git push origin –tags # 将本地所有标签一次性提交到git服务器

 

注意:如果想看之前某个标签状态下的文件,可以这样操作

1.git tag   查看当前分支下的标签

2.git  checkout v0.21   此时会指向打v0.21标签时的代码状态,(但现在处于一个空的分支上)

3. cat  test.txt   查看某个文件

git 知识总结

 

一、添加文件到Git仓库,分两步:
1.第一步,使用命令git add <file>,注意,可反复多次使用,添加多个文件;
2.第二步,使用命令git commit,完成。
二、要随时掌握工作区的状态,使用git status命令。
如果git status告诉你有文件被修改过,用git diff可以查看修改内容。
三、时光穿梭
1.HEAD指向的版本就是当前版本,因此,Git允许我们在版本的历史之间穿梭,使用命令git reset --hard commit_id
2.穿梭前,用git log可以查看提交历史,以便确定要回退到哪个版本。
3.要重返未来,用git reflog查看命令历史,以便确定要回到未来的哪个版本。
四、Git跟踪并管理的是修改,而非文件
1.git diff HEAD a.txt   查看文件的修改   git diff HEAD~3  ; git diff  <版本号,前6位>
2.
五.撤销修改
1.git checkout — a.txt
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commitgit add时的状态。
备注:也就是说,用了checkout —  命令后 , 编辑,git add后编辑或者git commit后编辑后的内容,将失效,回到前一次操作的状态
2.用命令git reset HEAD file可以把暂存区的修改撤销掉(unstage)
3.git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
4.丢弃工作区的修改  git checkout   a.txt
git reset HEAD a.txt    只是把暂存区的文件取出来,不会修改文件  commit 后,就不行了commit  后就用时光机吧
5.当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file
6.当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。
六、git reset 回退某一个版本  git revert  回退某一个版本生成一个新的commit
七、穿件分支和合并分支
1.查看分支:git branch
2.创建分支:git branch <name>
3.切换分支:git checkout <name>
4.创建+切换分支:git checkout -b <name>
5.合并某分支到当前分支:git merge <name>
6.删除分支:git branch -d <name>
八、解决冲突
1.当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。
2.git log --graph  查看分支合并图
3.git 可以帮你合并一些简单,当修改的同一个地方,无法解决的时候,就需要手动解决冲突问题了
九、bug修复
1.stash功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作;
2.git stash list命令看看stash记录
3.git stash apply 或者多个stash  用git stash apply stash@{1} 来恢复
4.stash用git stash drop来删除;git stash pop,恢复的同时把stash内容也删了;
十、小技巧
1.开发一个新feature,最好新建一个分支;
2.如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>强行删除。
十一、多人协作
1.首先,可以试图用git push origin branch-name推送自己的修改;
2.如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
3.如果合并有冲突,则解决冲突,并在本地提交;
4.没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!
5.如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name
备注:1.查看远程库信息,使用git remote -v
2.本地新建的分支如果不推送到远程,对其他人就是不可见的;
3.从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
4.在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
5.建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name
6.从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
十二、标签
1.命令git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id;
2.git tag -a <tagname> -m "blablabla..."可以指定标签信息;
3.git tag -s <tagname> -m "blablabla..."可以用PGP签名标签;
4.命令git tag可以查看所有标签。
5.git show <tagname>  查看标签的详细信息
操作标签:
1.命令git push origin <tagname>可以推送一个本地标签;
2.命令git push origin --tags可以推送全部未推送过的本地标签;
3.命令git tag -d <tagname>可以删除一个本地标签;
4.命令git push origin :refs/tags/<tagname>可以删除一个远程标签。
十三、忽略文件
1.忽略某些文件时,需要编写.gitignore
2.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!
3.所有配置文件可以直接在线浏览:https://github.com/github/gitignore
备注:对已经进入版本库的文件无效,除非删除版本库的内容,才能起作用
十四、配置别名
1.git st就表示git status   配置git config --global alias.st status  其他的类似
2.git checkout   :git config --global alias.co checkout
3.查看配置 git config --list 本地仓库;git config --global --list  查看全局的仓库配置
4.git last 查看最后一条commit
5.

git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"

 

总结一些比较好用的指令
1.谁动了我的奶酪   git blame a.txt
2.git log  –onelime  –graph     显示log
3.git reflog 列出历史操作的log;  git fsck --lost-found 这个更厉害
4.git grep  搜索内容

更多详细指令介绍参看链接:http://blog.xiaofangmoon.com/?p=21

svn 实例操作1

我打算一口气讲完SVN的使用,所以,在看之前呢,请先深深的吸一口气(怎么听着像黑龙公主),当然吸完后还是要呼出来的。不要憋着了。

我们可能希望一来就直接操作。列出一堆命令。详细的命令参数等信息,我们都可以加入 –help 选项获取,下面不会详细介绍。除非必要。现在先看下面的例子:

$svn –help

usage: svn <subcommand> [options] [args]

Subversion command-line client, version 1.6.12.

Type ‘svn help <subcommand>’ for help on a specific subcommand.

Type ‘svn –version’ to see the program version and RA modules

  or ‘svn –version –quiet’ to see just the version number.

Most subcommands take file and/or directory arguments, recursing

on the directories.  If no arguments are supplied to such a

command, it recurses on the current directory (inclusive) by default.

Available subcommands:

   add

   blame (praise, annotate, ann)

   cat

   changelist (cl)

   checkout (co)

   cleanup

   commit (ci)

   copy (cp)

   delete (del, remove, rm)

   diff (di)

   export

   help (?, h)

   import

   info

   list (ls)

   lock

   log

   merge

   mergeinfo

   mkdir

   move (mv, rename, ren)

   propdel (pdel, pd)

   propedit (pedit, pe)

   propget (pget, pg)

   proplist (plist, pl)

   propset (pset, ps)

   resolve

   resolved

   revert

   status (stat, st)

   switch (sw)

   unlock

   update (up)

Subversion is a tool for version control.

For additional information, see http://subversion.tigris.org/

好了,什么都出来了。一大堆信息。慢慢读吧。可是这样的方式,对我们使用SVN并无指导意义。什么时候用什么命令? 下面就来说一下SVN的基本使用,在此之前,还有两个重要的东西需要理解。

SVN 除了可以让你追溯历史,还有一个重要的功能,便是多人协作。我们要解决的问题不仅仅是可以从历史中恢复。还有如果多人同时修改一个文件,那么该以谁的为主呢?

所以在SVN中,我们有两种使用模式:

Lock-Modify-Unlock

简单的说就是,给需要修改的文件加锁,然后修改,然后解锁。

这是一个很好的办法。但是如果一个文件被锁住了,那么其他人就不能修改了。而此时如果是我在修改文件头,而你需要修改文件末尾的话,你也只能等我修改完。这样是很浪费你的时间的。所以我们又有另外一种模式。

Copy-Modify-Merge

这是一种很高级的模式,从库中拷贝一份,修改,然后根据拷贝的和库中的不同,在合并。为什么说高级呢,因为合并是一个很复杂的过程。很可能失败。但是这种方法却尽可能使大家不受影响。例如你和我同时修改一个文件,我改文件头,你改文件尾,然后一提交,就给合成一份了。不会互相打扰。事实上问题比这复杂的多。

好了,说了这么多废话。我们可以正式开始了。

虽然一般情况,我们是不用自己去创建一个SVN库的,现在为了说明流畅,我们从创建一个库开始。

$svnadmin create  /var/idp/repos

于是我们创建了一个SVN库。到下面看看

$ls /var/idp/repos

conf  db  format  hooks  locks  README.txt

我们的库就创建好了。这里不多说, svnadmin是一个高级命令,我们基本用不到。

导入需要管理的文件:

$svn import /home/madic/code file:///var/idp/repos -m “init code”

Adding         /home/madic/code/signo

Adding         /home/madic/code/signo/sigset.c

Adding  (bin)  /home/madic/code/signo/wait

Adding         /home/madic/code/signo/wait.c

Committed revision 1.

这里版本变为1,初始版本为0。  每次对库的操作改变,都会产生一个新的版本。版本是我们追溯历史的一个索引。在版本管理中非常重要。当前库中最新的版本可以用HEAD表示。HEAD版也就是库中最新版本。

我们把 /home/madic/code 文件下的文件目录都导入了svn库,从此,他们就被时光机管理,数据永不丢失(当然你干掉时光机,数据还是会丢失的)。

注意 (bin) 表示这是一个二进制文件,非文本文件。

除了import 外,我们还可以用 svn add 添加文件。

使用list命令查看库中文件

$svn  list  file:///var/idp/repos

signo/

signo/sigset.c

signo/wait

signo/wait.c

现在,我们开始工作了。那么,就使用 CMC(Copy-Modify-Merge)模式吧。

如何创建一个Working Copy 呢?看:

$svn checkout file:///var/idp/repos  /home/madic/code_svn

A    /home/madic/code_svn/signo

A    /home/madic/code_svn/signo/sigset.c

A    /home/madic/code_svn/signo/wait

A    /home/madic/code_svn/signo/wait.c

Checked out revision 1.

恭喜我们现在拥有一个Working Copy了,你就在这个WorkingCopy中折腾吧,只要不提交,那么对库来说就没有任何影响。就算你用了 rm 不小心删除了某个文件,不用着急。使用update便可以找回。

$svn update

svn update

Restored ‘main.c’

At revision 1.

这里,我们删掉 main.c 然后到WC 下,执行 svn update 命令,就找回main.c了。

在Working Copy 目录中,Subversion如何知道文件的情况呢,其实这些都是 .svn的功劳。每个SVN管理的WC中,都会有一个隐藏的文件夹,.svn

$ls -la .svn

drwxr-xr-x  6 madic madic 4096 2011-07-26 11:00 .svn

如果不小心误删除,也可以用svn update恢复。

接下来,我们开始正常的编辑文件。编辑之前,已定要使用svn update 来确保你编辑的文件是最新的。如果不是最新的,那么这个文件就是 Out-of-date了,此时你的编辑就不能被提交到库中。编辑时,你不必使用svn的命令了。你可以用任何编辑器编辑文件。当你编辑完成后保存。

$svn status -q

M       readme.txt

这个M表示此文件被修改了。于是我们需要把她提交到库,这样别人才能看到我修改的东西。

$svn commit -m “我修改了文件内容” readme.txt

svn commit -m “modify” readme.txt

Sending        readme.txt

Transmitting file data .

Committed revision 8.

文件被提交,版本更新到8.

这样,我们就完成了一个最基本的SVN操作流程。也许如果没有什么大事,我们就到此结束了。难道还有什么问题吗?

上面提到,我们在修改的同时,可能别人也在修改。所以要尽量在每次修改的时候,保持我们的WC和库中的是同步的,也就是最新的。我们使用svn update来使自己的working copy是最新的。我们也可以用一个新的命令来看WC的状态。

$svn status -u -v readme.txt

M                8        8  madic        readme.txt

M     *          8        3  madic        foo.c

我们看到readme.txt 目前是M(modify)状态,说明此文件被改了。当前版本和最新版本都是8 ,用户是madic。

而foo.c 多了个星号,这表明foo.c 已经out-of-date 了。也就是说,我们在修改的版本,已经不是最新的了。在我们修改的时候,已经有人提交了新的版本。

除了 M表示修改,还有 U表示更新,D表示删除,A 表示新增, C表示冲突。

有时候有两个MM,此时并非表示美眉,而是文件的内容和属性都被改变了。

同样UU表示属性和内容都更新了。

所以,在我们提交以后,并非就结束了,此时,我们需要查看一下状态。如果有文件处于C状态,那么说明我们遇到麻烦了。因为C表示冲突了,一定是某个人和我们在改同一个地方。

这时,最好的办法是直接找到和我们冲突的修改人。然后沟通吧。是你死还是我亡。冲突实际上是在svn update的时候发生的。由于我编辑的太久了,你已经提交了一个新版本,我提交的时候,提示 out-of-date了,于是我svn update,冲突出现:

$ svn update

Conflict discovered in ‘readme.txt’.

Select: (p) postpone, (df) diff-full, (e) edit,

        (mc) mine-conflict, (tc) theirs-conflict,

        (s) show all options:

这时几个选择出现了,postpone 的意思是暂时推后处理,我可能要和那个和我冲突的家伙商量一番。 diff-full,则是比比看,到底什么地方冲突了。edit,修改冲突合并的文件。 mc,这个霸道,直接用我的。 tc , 底气不足,还是用别人修改的吧。我们一切三思而后行,所以选择了p,然后在看看文件目录下有什么。

多了三个文件:

readme.txt.mine  readme.txt.r9  readme.txt  readme.txt.r8

我们来说说这三个文件:readme.txt.mine 后最 mine是本地最新的。

readme.txt.r9 很明显,是版本9的,这个版本正式库中最新的版本。

readme.txt.r8  这个版本是库中最新的版本的前一版本。

我们来看一下,现在的readme.txt

$cat readme.txt

<<<<<<< .mine

hi

=======

hello

>>>>>>> .r9

很明显,我的版本中是hi ,而r9 的是hello。

好吧,我明白了。现在假设我们很明白,或者已经和发生冲突的文件的编辑同事商量好了。我们就要解决冲突了。

首先,上面说的三个文件,如果存在,我们就提交不了。

其次,需要选择一个解决方法。

$svn resolve –accepting working reademe.txt

svn resolve 是解决冲突的命令。解决的方法由–accepting 选项决定。

base  恢复到冲突前的一个版本。

mine-full  恢复到以我的修改为主的版本

their-full  恢复到库中最新版本

working  手动解决

所以,上面的那句命令其实还有问题,因为我们还没有手工修改文件。

于是我们打开readme.txt,去掉哪些冲突标识

<<<<<<< .mine

hi

=======

hello

>>>>>>> .r9

修改为

No hi no hello

然后保存readme.txt

在使用

$svn resolve –accepting working reademe.txt

注意,这一步以后,并没有真正完成冲突解决。

$svn commit -m “conflict resole”

Sending        readme.txt

Transmitting file data .

Committed revision 10.

这次提交OK。冲突至此解决。

有时候,我们编写到一半发现有人提交了更新或者是越写越乱,我们想放弃这次编辑,恢复到上一个版本,当然,我们可以直接rm掉,然后update,我们也可以这样:

$svn revert readme.txt

Reverted ‘readme.txt’

问题解决以后,请使用svn status 查看一下状态,是否正常了。

$svn status -vu readme.txt

                10       10 yinshaoxin   readme.txt

Status against revision:     10

没有什么M,C,* ,D, ? 这些,说明状态正常。

对于我们操作的这些,我们可以通过历史svn log来查看状态。

$svn log

r9 | yinshaoxin | 2011-07-26 13:39:12 +0800 (Tue, 26 Jul 2011) | 1 line

shaoxin

————————————————————————

r8 | madic | 2011-07-26 11:12:47 +0800 (Tue, 26 Jul 2011) | 1 line

modify

————————————————————————

r7 | madic | 2011-07-26 09:35:51 +0800 (Tue, 26 Jul 2011) | 1 line

code

————————————————————————

r6 | madic | 2011-07-20 15:43:52 +0800 (Wed, 20 Jul 2011) | 1 line

pa

————————————————————————

r5 | madic | 2011-07-20 15:42:19 +0800 (Wed, 20 Jul 2011) | 1 line

p

————————————————————————

r4 | madic | 2011-07-20 10:40:03 +0800 (Wed, 20 Jul 2011) | 1 line

dir

————————————————————————

r3 | madic | 2011-07-19 14:01:49 +0800 (Tue, 19 Jul 2011) | 1 line

keywords

————————————————————————

r2 | madic | 2011-07-19 13:58:24 +0800 (Tue, 19 Jul 2011) | 1 line

new test

————————————————————————

r1 | madic | 2011-07-15 16:56:05 +0800 (Fri, 15 Jul 2011) | 1 line

ci chage

————————————————————————

天哪,所有的svn日志都显示出来了。我们可以使用r来确定一个范围。

这就是时光机的历史查看了。来吧,想看哪一个版本的。

$svn log -r 5:9

————————————————————————

r5 | madic | 2011-07-20 15:42:19 +0800 (Wed, 20 Jul 2011) | 1 line

p

————————————————————————

r6 | madic | 2011-07-20 15:43:52 +0800 (Wed, 20 Jul 2011) | 1 line

pa

————————————————————————

r7 | madic | 2011-07-26 09:35:51 +0800 (Tue, 26 Jul 2011) | 1 line

code

————————————————————————

r8 | madic | 2011-07-26 11:12:47 +0800 (Tue, 26 Jul 2011) | 1 line

modify

————————————————————————

r9 | yinshaoxin | 2011-07-26 13:39:12 +0800 (Tue, 26 Jul 2011) | 1 line

shaoxin

————————————————————————

注意  -r 5:9  和 -r 9:5 是不同的顺序显示。

当然也可以指定一个文件的版本日志。

使用log注意,当你提交一个版本后,log并看不到这个日志。

因为 commit 和 update是独立的。commit并不更新本地版本。我们只有使用 update以后,在使用log则可以看到。

还有,如果你使用svn log 不指定路径的话,那么默认的是当前的目录。这样,对于其他目录的log,我们只有一条空日志。

$——————————————-

最后不要像我一样,日志都是乱七八糟,请重视日志,因为在以后查找问题梳理版本变化的时候,会对你有很大帮助。

好了,从现在开始,你已经基本掌握SVN的用法了。如果具体命令参数不会用,请使用 help 。

如果你想了解的更多一点,那么我们继续看下一章。

转自:http://airu.iteye.com/blog/1142301

git 基本指令操作

取得项目的 Git 仓库

有两种取得 Git 项目仓库的方法。第一种是在现存的目录下,通过导入所有文件来创建新的 Git 仓库。第二种是从已有的 Git 仓库克隆出一个新的镜像仓库来。

  • 从当前目录初始化
    要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:

    $ git init
    

    初始化后,在当前目录下会出现一个名为 .git 的目录,所有 Git 需要的数据和资源都存放在这个目录中。不过目前,仅仅是按照既有的结构框架初始化好了里边所有的文件和目录,但我们还没有开始跟踪管理项目中的任何一个文件。(在第九章我们会详细说明刚才创建的 .git 目录中究竟有哪些文件,以及都起些什么作用。)

    如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交:

    $ git add *.c
    $ git add README
    $ git commit -m 'initial project version'
    

    稍后我们再逐一解释每条命令的意思。不过现在,你已经得到了一个实际维护着若干文件的 Git 仓库。

  • 从现有仓库克隆
    如果想对某个开源项目出一份力,可以先把该项目的 Git 仓库复制一份出来,这就需要用到 git clone命令。如果你熟悉其他的 VCS 比如 Subversion,你可能已经注意到这里使用的是 clone 而不是checkout 。这是个非常重要的差别,Git 收取的是项目历史的所有数据(每一个文件的每一个版本),服务器上有的数据克隆之后本地也都有了。实际上,即便服务器的磁盘发生故障,用任何一个克隆出来的客户端都可以重建服务器上的仓库,回到当初克隆时的状态(可能会丢失某些服务器端的挂钩设置,但所有版本的数据仍旧还在,有关细节请参考第四章)。克隆仓库的命令格式为 git clone [url] 。比如,要克隆 Ruby 语言的 Git 代码仓库 Grit,可以用下面的命令:

    $ git clone git://github.com/schacon/grit.git
    

    这会在当前目录下创建一个名为 “grit” 的目录,其中内含一个 .git 的目录,并从同步后的仓库中拉出所有的数据,取出最新版本的文件拷贝。如果进入这个新建的 grit 目录,你会看到项目中的所有文件已经在里边了,准备好后续的开发和使用。如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令最后指定:

    $ git clone git://github.com/schacon/grit.git mygrit
    

    唯一的差别就是,现在新建的目录成了 mygrit,其他的都和上边的一样。

    Git 支持许多数据传输协议。之前的例子使用的是 git:// 协议,不过你也可以用 http(s):// 或者user@server:/path.git 表示的 SSH 传输协议。我们会在后面详细介绍所有这些协议在服务器端该如何配置使用,以及各种方式之间的利弊。

2.2 常用指令

2.2.1 获得git仓库

使用 git-clone 命令下载一个仓库的拷贝。

        # git itself (approx. 10MB download):
$ git clone git://git.kernel.org/pub/scm/git/git.git
        # the Linux kernel (approx. 150MB download):
$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

2.2.2 git add

这是个多功能命令,根据目标文件的状态不同,此命令的效果也不同:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等

$ git add . # 將資料先暫存到 staging area, add 之後再新增的資料, 於此次 commit 不會含在裡面.
$ git add filename
$ git add modify-file # 修改過的檔案, 也要 add. (不然 commit 要加上 -a 的參數)
$ git add -u # 只加修改過的檔案, 新增的檔案不加入.
$ git add -i # 進入互動模式
  • 描述
  • 参数
  • 配置
  • 例子

2.2.3 git push (远程仓库名) (分支名)

2.3 实作练习

2.3.1 Git 建立 Local Repository

1:  $ mkdir project; 
2:  $ cd project
3:  $ git init
4:  $ echo "hello" > hello.txt
5:  $ git add .
6:  $ git commit -m 'initial'

2.3.2 Git clone 資料, 資料修改後上傳

1:  $ git clone http://git.example.com/project.git
2:  $ cd project
3:  $ touch new_file.txt
4:  $ git add .
5:  $ git commit -m 'add new_file.txt'
6:  $ git push origin master
7:  $ git pull # 拉看看有沒有更新

2.4 扩展应用

2.4.1 在 Google Code 中使用 Git

2.5 安装

2.5.1 在 Linux 上安装

如果要在 Linux 上安装预编译好的 Git 二进制安装包,可以直接用系统提供的包管理工具。

在 Fedora 上用 yum 安装:

$ yum install git-core

在 Ubuntu 这类 Debian 体系的系统上,可以用 apt-get 安装:

$ apt-get instal git-core

2.5.2 在 Windows 上安装

在 Windows 上安装 Git 同样轻松,有个叫做 msysGit 的项目提供了安装包,可以从 Google Code 的页面上下载安装文件(.exe):

http://code.google.com/p/msysgit

完成安装之后,就可以使用命令行的 git 工具(已经自带了 ssh 客户端)了,另外还有一个图形界面的 Git 项目管理工具。

2.5.3 在 Mac 上安装

在 Mac 上安装 Git 有两种方式。最容易的当属使用图形化的 Git 安装工具,界面如图 1-7,下载地址在:

http://code.google.com/p/git-osx-installer

另一种是通过 MacPorts (http://www.macports.org) 安装。如果已经装好了 MacPorts,用下面的命令安装 Git:

$ sudo port install git-core +svn +doc +bash_completion +gitweb

这种方式就不需要再自己安装依赖库了,Macports 会帮你搞定这些麻烦事。一般上面列出的安装选项已经够用,要是你想用 Git 连接 Subversion 的代码仓库,还可以加上 +svn 选项,具体将在第八章作介绍。

2.6 配置

Git 提供了一个叫做 git config 的工具(译注:实际是 git-config 命令,只不过可以通过 git 加一个名字来呼叫此命令。),专门用来配置或读取相应的工作环境变量。而正是由这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:

  • /etc/gitconfig 文件 :系统中对所有用户都普遍适用的配置。若使用 git config 时用 --system 选项,读写的就是这个文件。
  • ~/.gitconfig 文件 :用户目录下的配置文件只适用于该用户。若使用 git config 时用 --global 选项,读写的就是这个文件。
  • 当前项目的 git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前项目有效。

每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆 盖 /etc/gitconfig 中的同名变量。

2.6.1 用户信息

第一个要配置的是你个人的用户名称和电子邮件地址。这两条配置很重要,每次 Git 提交时都会引用这两条信息,说明是谁提交了更新,所以会随更新内容一起被永久纳入历史记录:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的项目都会默认使用这里配置的用户信息。如果要在某个特定的项目中使用其他名字或者电邮,只要去掉 --global选项重新配置即可,新的设定保存在当前项目的 .git/config 文件里。

2.6.2 文本编辑器

接下来要设置的是默认使用的文本编辑器。Git 需要你输入一些额外消息的时候,会自动调用一个外部文本编辑器给你用。默认会使用操作系统指定的默认编辑器,一般可能会是 Vi 或者 Vim。如果你有其他偏好,比如 Emacs 的话,可以重新设置:

$ git config --global core.editor emacs

2.6.3 差异分析工具

还有一个比较常用的是,在解决合并冲突时使用哪种差异分析工具。比如要改用 vimdiff 的话:

$ git config --global merge.tool vimdiff

Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。当然,你也可以指定使用自己开发的工具,具体怎么做可以参阅第七章。

2.6.4 查看配置信息

要检查已有的配置信息,可以使用 git config --list 命令:

$ git config --list
user.name=Scott Chacon
user.email=schacon@gmail.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...

有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 etc/gitconfig 和 ~.gitconfig),不过最终 Git 实际采用的是最后一个。

也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可,像这样:

$ git config user.name
Scott Chacon

2.7 获取帮助

想了解 Git 的各式工具该怎么用,可以阅读它们的使用帮助,方法有三:

$ git help <verb>
$ git <verb> --help
$ man git-<verb>

比如,要学习 config 命令可以怎么用,运行:

$ git help config

我们随时都可以浏览这些帮助信息而无需连网。不过,要是你觉得还不够,可以到 Frenode IRC 服务器(irc.freenode.net)上的 #git 或 #github 频道寻求他人帮助。这两个频道上总有着上百号人,大多都有着丰富的 git 知识,并且乐于助人。

2.8 常用指令

2.8.1 Git 新增檔案

$ git add . # 將資料先暫存到 staging area, add 之後再新增的資料, 於此次 commit 不會含在裡面.
$ git add filename
$ git add modify-file # 修改過的檔案, 也要 add. (不然 commit 要加上 -a 的參數)
$ git add -u # 只加修改過的檔案, 新增的檔案不加入.
$ git add -i # 進入互動模式

2.8.2 Git 刪除檔案

$ git rm filename

2.8.3 Git 修改檔名、搬移目錄

$ git mv filename new-filename

2.8.4 Git status 看目前的狀態

$ git status # 看目前檔案的狀態

2.8.5 Git Commit

$ git commit
$ git commit -m 'commit message'
$ git commit -a -m 'commit -message' # 將所有修改過得檔案都 commit, 但是 新增的檔案 還是得要先 add.
$ git commit -a -v # -v 可以看到檔案哪些內容有被更改, -a 把所有修改的檔案都 commit

2.8.6 Git 產生新的 branch

$ git branch # 列出目前有多少 branch
$ git branch new-branch # 產生新的 branch (名稱: new-branch), 若沒有特別指定, 會由目前所在的 branch / master 直接複製一份.
$ git branch new-branch master # 由 master 產生新的 branch(new-branch)
$ git branch new-branch v1 # 由 tag(v1) 產生新的 branch(new-branch)
$ git branch -d new-branch # 刪除 new-branch
$ git branch -D new-branch # 強制刪除 new-branch
$ git checkout -b new-branch test # 產生新的 branch, 並同時切換過去 new-branch
$ # 與 remote repository 有關
$ git branch -r # 列出所有 Repository branch
$ git branch -a # 列出所有 branch

2.8.7 Git checkout 切換 branch

$ git checkout branch-name # 切換到 branch-name
$ git checkout master # 切換到 master
$ git checkout -b new-branch master # 從 master 建立新的 new-branch, 並同時切換過去 new-branch
$ git checkout -b newbranch # 由現在的環境為基礎, 建立新的 branch
$ git checkout -b newbranch origin # 於 origin 的基礎, 建立新的 branch
$ git checkout filename # 還原檔案到 Repository 狀態
$ git checkout HEAD . # 將所有檔案都 checkout 出來(最後一次 commit 的版本), 注意, 若有修改的檔案都會被還原到上一版. (git checkout -f 亦可)
$ git checkout xxxx . # 將所有檔案都 checkout 出來(xxxx commit 的版本, xxxx 是 commit 的編號前四碼), 注意, 若有修改的檔案都會被還原到上一版.
$ git checkout -- $ # 恢復到上一次 Commit 的狀態($ 改成檔名, 就可以只恢復那個檔案)

2.8.8 Git diff

$ git diff master # 與 Master 有哪些資料不同
$ git diff --cached # 比較 staging area 跟本來的 Repository
$ git diff tag1 tag2 # tag1, 與 tag2 的 diff
$ git diff tag1:file1 tag2:file2 # tag1, 與 tag2 的 file1, file2 的 diff
$ git diff # 比較 目前位置 與 staging area
$ git diff --cached # 比較 staging area 與 Repository 差異
$ git diff HEAD # 比較目前位置 與 Repository 差別
$ git diff new-branch # 比較目前位置 與 branch(new-branch) 的差別
$ git diff --stat

2.8.9 Git Tag

$ git tag v1 ebff # log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容, 設定簡短好記得 Tag: v1
$ git tag 中文 ebff # tag 也可以下中文, 任何文字都可以
$ git tag -d 中文 # 把 tag=中文 刪掉

2.8.10 Git log

$ git log # 將所有 log 秀出
$ git log --all # 秀出所有的 log (含 branch)
$ git log -p # 將所有 log 和修改過得檔案內容列出
$ git log --stat --summary # 查每個版本間的更動檔案和行數
$ git log filename # 這個檔案的所有 log
$ git log directory # 這個目錄的所有 log
$ git log -S'foo()' # log 裡面有 foo() 這字串的.
$ git log --no-merges # 不要秀出 merge 的 log
$ git log --since="2 weeks ago" # 最後這 2週的 log
$ git log --pretty=oneline # 秀 log 的方式
$ git log --pretty=short # 秀 log 的方式
$ git log --pretty=format:'%h was %an, %ar, message: %s'
$ git log --pretty=format:'%h : %s' --graph # 會有簡單的文字圖形化, 分支等.
$ git log --pretty=format:'%h : %s' --topo-order --graph # 依照主分支排序
$ git log --pretty=format:'%h : %s' --date-order --graph # 依照時間排序

2.8.11 Git show

$ git show ebff # 查 log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容
$ git show v1 # 查 tag:v1 的修改內容
$ git show v1:test.txt # 查 tag:v1 的 test.txt 檔案修改內容
$ git show HEAD # 此版本修改的資料
$ git show HEAD^ # 前一版修改的資料
$ git show HEAD^^ # 前前一版修改的資料
$ git show HEAD~4 # 前前前前一版修改的資料

2.8.12 Git reset 還原

$ git reset --hard HEAD # 還原到最前面
$ git reset --hard HEAD~3
$ git reset --soft HEAD~3
$ git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)

2.8.13 Git grep

$ git grep "te" v1 # 查 v1 是否有 "te" 的字串
$ git grep "te" # 查現在版本是否有 "te" 的字串

2.8.14 Git stash 暫存

$ git stash # 丟進暫存區
$ git stash list # 列出所有暫存區的資料
$ git stash pop # 取出最新的一筆, 並移除.
$ git stash apply # 取出最新的一筆 stash 暫存資料. 但是 stash 資料不移除
$ git stash clear # 把 stash 都清掉

2.8.15 Git merge 合併

$ git merge
$ git merge master
$ git merge new-branch
$ 下述轉載自: ihower 的 Git 版本控制系統(2) 開 branch 分支和操作遠端 repo.x

    $ Straight merge 預設的合併模式,會有全部的被合併的 branch commits 記錄加上一個 merge-commit,看線圖會有兩條 Parents 線,並保留所有 commit log。
    $ Squashed commit 壓縮成只有一個 merge-commit,不會有被合併的 log。SVN 的 merge 即是如此。
    $ cherry-pick 只合併指定的 commit
    $ rebase 變更 branch 的分支點:找到要合併的兩個 branch 的共同的祖先,然後先只用要被 merge 的 branch 來 commit 一遍,然後再用目前 branch 再 commit 上去。這方式僅適合還沒分享給別人的 local branch,因為等於砍掉重練 commit log。

指令操作

    $ git merge <branch_name> # 合併另一個 branch,若沒有 conflict 衝突會直接 commit。若需要解決衝突則會再多一個 commit。
    $ git merge --squash <branch_name> # 將另一個 branch 的 commit 合併為一筆,特別適合需要做實驗的 fixes bug 或 new feature,最後只留結果。合併完不會幫你先 commit。
    $ git cherry-pick 321d76f # 只合併特定其中一個 commit。如果要合併多個,可以加上 -n 指令就不會先幫你 commit,這樣可以多 pick幾個要合併的 commit,最後再 git commit 即可。

2.8.16 Git blame

$ git blame filename # 關於此檔案的所有 commit 紀錄

2.8.17 Git 還原已被刪除的檔案

$ git ls-files -d # 查看已刪除的檔案
$ git ls-files -d | xargs git checkout -- # 將已刪除的檔案還原

2.8.18 Git 維護

$ git gc # 整理前和整理後的差異, 可由: git count-objects 看到.
$ git fsck --full

2.8.19 Git revert 資料還原

$ git revert HEAD # 回到前一次 commit 的狀態
$ git revert HEAD^ # 回到前前一次 commit 的狀態
$ git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)
$ git checkout filename # 從 unstaging 狀態回到最初 Repository 的檔案(檔案內容變回修改前)

以下與 遠端 Repository 相關

2.8.20 Git remote 維護遠端檔案

$ git remote
$ git remote add new-branch http://git.example.com.tw/project.git # 增加遠端 Repository 的 branch(origin -> project)
$ git remote show # 秀出現在有多少 Repository
$ git remote rm new-branch # 刪掉
$ git remote update # 更新所有 Repository branch
$ git branch -r # 列出所有 Repository branch

2.8.21 抓取 / 切換 Repository 的 branch

$ git fetch origin
$ git checkout --track -b reps-branch origin/reps-branch # 抓取 reps-branch, 並將此 branch 建立於 local 的 reps-branch

2.8.22 刪除 Repository 的 branch

$ git push origin :heads/reps-branch

3 patch文件的结构

补丁头

补丁头是分别由—/+++开头的两行,用来表示要打补丁的文件。—开头表示旧文件,+++开头表示新文件。

一个补丁文件中的多个补丁

一个补丁文件中可能包含以—/+++开头的很多节,每一节用来打一个补丁。所以在一个补丁文件中可以包含好多个补丁。

块是补丁中要修改的地方。它通常由一部分不用修改的东西开始和结束。他们只是用来表示要修改的位置。他们通常以@@开始,结束于另一个块的开始或者一个新的补丁头。

块的缩进

块会缩进一列,而这一列是用来表示这一行是要增加还是要删除的。

块的第一列

+号表示这一行是要加上的。

-号表示这一行是要删除的。

没有加号也没有减号表示这里只是引用的而不需要修改。

原文链接:http://blog.csdn.net/tody_guo/article/details/7528003