Git 学习总结

jopen 6年前

优点:
支持离线工作;本地提交可以稍后提交到服务器上。
Git 中的每个工作树都包含一个具有完整项目历史的仓库。
没有哪一个 Git 仓库会天生比其他仓库更重要。
Git 跟SVN一样有自己的集中式版本库或服务器。
Git是分布式的,SVN不是,这是Git和其它非分布式的版本控制系统(SVN,CVS)最核心的区别。

Git与SVN 的区别
每个开发人员从中心版本库的服务器上check out代码后会在自己的机器上克隆一个自己的版本库。
如果你被困在一个不能连接网络的地方时,就像在飞机上,地下室,电梯里等,你仍然能够提交文件,查看历史版本记录,创建项目分支等。(无网络也能)
开源软件:创建一个分支,向项目团队发送一个推请求。就能将你的代码发送给项目团队。
.git 目录是处于你的机器上的一个克隆版的版本库,它拥有中心版本库上所有的东西,例如标签、分支、版本记录等。
Git 分支和SVN的分支不同:分支在SVN中一点不特别,就是版本库中的另外的一个目录。如果你想知道是否合并了一个分支,你需要手工运行像这样的命令svn propget svn:mergeinfo,来确认代码是否被合并。
git:你可以从同一个工作目录下快速的在几个分支间切换。你很容易发现未被合并的分支,你能简单而快捷的合并这些文件。
SVN的版本号实际是任何一个相应时间的源代码快照,它是从CVS进化到SVN的最大的一个突破。
Git 可以使用SHA-1来唯一的标识一个代码快照
Git 的内容完整性要优于SVN
Git 的内容存储使用的是SHA-1哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。


CVS-SVN-GIT综合比较
(1)版本库模型:有客户端/服务器和分布式两种模式。
在客户端/服务器模式下,每一用户通过客户端访问位于服务器的主版本库,每一客户机只需保存它所关注的文件副本,对当前工作副本(working copy)的更改只有在提交到服务器之后,其它用户才能看到对应文件的修改。
分布式模式下,这些源码版本库副本间是对等的实体,用户的机器出了保存他们的工作副本外,还拥有本地版本库的  历史信息(历史版本信息)  。
(2)并发模式:描述了当同时对同一工作副本/文件进行更改或编辑时,如何管理这种冲突以避免产生无意义的数据,有排它锁和合并模式。
在排它锁模式下,只有发出请求并获得当前文件排它锁的用户才能对对该文件进行更改。
而在合并模式下,用户可以随意编辑或更改文件,但可能随时会被通知存在冲突(两个或多个用户同时编辑同一文件),于是版本控制工具或用户需要  合并更改  以解决这种冲突。
(3)历史模式:描述了如何在版本库中存贮文件的更改信息,有快照和改变集两种模式。
在快照模式下,版本库会分别存储更改发生前后的工作副本;
在改变集模式下,版本库除了保存更改发生前的工作副本外,只保存更改发生后的改变信息。
(4)变更范围
描述了版本编号是针对单个文件还是整个目录树。
(5)网络协议
描述了多个版本库间进行同步时采用的网络协议。
(6)原子提交性
描述了在提交更改时,能否保证所有更改要么全部提交或合并,要么不会发生任何改变。
(7)部分克隆
是否支持只拷贝版本库中特定的子目录。

名称  版本库模型    并发模式         历史模式         变更范围  网络协议   原子提交性 部分克隆
CVS  Client-server Merge Changeset File  Pserver,ssh No Yes
SVN  Client-server 3-way merge, recursive  Changeset and  custom (svn), custom (svn) over ssh,
merge, octopus merge Snapshot Tree  HTTP and SSL (usingWebDAV) Yes Yes


Git  Distributed    Merge or lock Snapshot Tree  custom, custom over ssh, rsync,
 HTTP/HTTPS, email, bundles Yes No
基础命令:
初始化一个新的代码仓库:

第一种是在现存的目录下,通过导入所有文件来创建新的 Git 仓库。
在工作目录中初始化新仓库:要对现有的某个项目开始用 Git 管理,只需到此项目所在的目录,执行:
$ git init
第二种是从已有的 Git 仓库克隆出一个新的镜像仓库来。初次克隆某个仓库时,工作目录中的所有文件都属于已跟踪文件,且状态为未修改。
这里克隆,Git 会自动为你将此远程仓库命名为 origin,并下载其中所有的数据,建立一个指向它的 master 分支的指针,在本地命名为 origin/master,但你无法在本地更改其(远程仓库)数据。
在克隆仓库时,Git 通常会自动创建一个名为 master 的分支来跟踪 origin/master。这正是 git push 和 git pull 一开始就能正常工作的原因。
接着,Git 建立一个属于你自己的本地 master 分支,始于 origin 上 master 分支相同的位置,你可以就此开始工作。
从现有仓库克隆,这里使用的是 clone 而不是 checkout。Git 收取的是项目历史的所有数据(每一个文件的每一个版本),服务器上有的数据克隆之后本地也都有了。命令格式为 git clone [url],当前目录下创建一个名为“grit”的目录,其中包含一个 .git 的目录
git clone 命令本质上就是自动创建了本地的 master 分支用于跟踪远程仓库中的 master 分支(假设远程仓库确实有 master 分支)
(克隆操作会自动使用默认的 master 和 origin 名字)
拷贝一个 Git 仓库到本地,让自己能够查看该项目,或者进行修改
$ git clone git://github.com/schacon/grit.git
如果希望在克隆的时候,自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:
$ git clone git://github.com/schacon/grit.git mygrit
做一些适当配置
开始或停止跟踪某些文件:
如果当前目录下有几个文件想要纳入版本控制,需要先用 git add 命令告诉 Git 开始对这些文件进行跟踪,然后提交:
$ git add .c
$ git add README
$ git commit -m 'initial project version'
git add 的潜台词就是把目标文件快照放入暂存区域,也就是 add file into staged area,同时未曾跟踪过的文件标记为需要跟踪。

我们手上已经有了一个真实项目的 Git 仓库,并从这个仓库中取出了所有文件的工作拷贝。接下来,对这些文件作些修改,在完成了一个阶段的目标之后,提交本次更新到仓库。


检查当前文件状态
要确定哪些文件当前处于什么状态,可以用 git status 命令。如果在克隆仓库之后立即执行此命令,会看到类似这样的输出:
$ git status # On branch master nothing to commit (working directory clean)
当前没有任何跟踪着的文件
也没有任何文件在上次提交后更改过
当前目录下没有出现任何处于未跟踪的新文件,否则 Git 会在这里列出来。
显示了当前所在的分支
会有以下两种状态:
Changes to be committed:处于staged的文件
Changed but not updated:处于modified的文件
注:一个文件可以同时处于上面两种状态,就是在加入staged的文件又被修改后
暂存或提交某些更新
修改下之前已跟踪过的文件,出现在 “Changed but not updated” 这行下面,说明已跟踪文件的内容发生了变化,但还没有放到暂存区。
要暂存这次更新,需要运行git add 命令(这是个多功能命令,根据目标文件的状态不同,此命令的效果也不同:可以用它开始跟踪新文件,
或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等)。
$ git add benchmarks.rb
提交更新,在此之前,请一定要确认还有什么修改过的或新建的文件还没有 git add 过,否则提交的时候不会记录这些还没暂存起来的变化。
提交时记录的是放在暂存区域的快照,任何还未暂存的仍然保持已修改状态,可以在下次提交时纳入版本管理。
每一次运行提交操作,都是对你项目作一次快照,以后可以回到这个状态,或者进行比较。
Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit 加上-a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:
$ git commit
$ git commit -m 'initial project version'
$ git commit -a -m 'added new benchmarks'

查看已暂存和未暂存的更新
git status 的显示比较简单,仅仅是列出了修改过的文件,如果要查看具体修改了什么地方,可以用 git diff 命令。
它已经能回答我们的两个问题了:当前做的哪些更新还没有暂存?有哪些更新已经暂存起来准备好了下次提交?
git diff 会使用文件补丁的格式显示具体添加和删除的行。
$ git diff
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容。
$ git diff --cached
要看已经暂存起来的文件和上次提交时的快照之间的差异,可以用 git diff --cached 命令。
移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。
用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changed but not updated” 部分(也就是_未暂存_清单)
$ git rm grit.gemspec
rm 'grit.gemspec'
$ git status
删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f
$ git rm -f grit.gemspec
要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项即可
$ git rm --cached readme.txt
后面可以列出文件或者目录的名字,也可以使用 glob 模式。比方说:
$ git rm log/\
.log
递归删除当前目录及其子目录中所有 ~ 结尾的文件
$ git rm *~
仅仅删除指定目录下的文件而不会递归匹配。
$ git rm log/*.log
移动文件
要在 Git 中对文件改名
$ git mv file_from file_to
运行 git mv 就相当于运行了下面三条命令:
$ mv README.txt README $ git rm README.txt $ git add README
让 Git 忽略某些文件,或是名称符合特定模式的文件
我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。可以创建一个名为 .gitignore 的文件,列出要忽略的文件模式。要养成一开始就设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
$ cat .gitignore .[oa] ~
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。
第二行告诉 Git 忽略所有以波浪符(~)结尾的文件
文件 .gitignore 的格式规范如下:
# 此为注释 – 将被 Git 忽略
.a       # 忽略所有 .a 结尾的文件
!lib.a    # 但 lib.a 除外
/TODO     # 仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO
build/    # 忽略 build/ 目录下的所有文件
doc/
.txt # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
● 所有空行或者以注释符号 # 开头的行都会被 Git 忽略。
● 可以使用标准的 glob 模式匹配。 匹配模式最后跟反斜杠(/)说明要忽略的是目录。 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。
如何既快且容易地撤消犯下的小错误
修改最后一次提交,我们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操作,可以使用 --amend选项重新提交:
$ git commit --amend
刚才提交完没有作任何改动,直接运行此命令的话,相当于有机会重新编辑提交说明,但将要提交的文件快照和之前的一样。
$ git commit --amend -m 'message'
如果刚才提交时忘了暂存某些修改,可以先补上暂存操作,然后再运行 --amend 提交
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
上面的三条命令最终只是产生一个提交,第二个提交命令修正了第一个的提交内容。
取消已经暂存的文件
$ git reset HEAD benchmarks.rb
benchmarks.rb: locally modified
取消对文件的修改,该如何取消修改,回到之前的状态(也就是修改之前的版本)呢?
$ git checkout -- benchmarks.rb
任何已经提交到 Git 的都可以被恢复。即便在已经删除的分支中的提交,或者用 --amend 重新改写的提交,都可以被恢复


如何浏览项目的更新历史,查看某两次更新之间的差异
查看提交历史,在提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,可以使用 git log 命令查看
$ git log
常用 -p 选项展开显示每次提交的内容差异,用 -2 则仅显示最近的两次更新:
$ git log -p -2
仅显示简要的增改行数统计
$ git log --stat
--pretty 选项,可以指定使用完全不同于默认格式的方式展示提交历史。另外还有 short,full 和fuller 可以用
$ git log --pretty=oneline
定制要显示的记录格式
$ git log --pretty=format:"%h - %an, %ar : %s"
其他常用的选项及其释义。
选项 说明
-p 按补丁格式显示每个更新之间的差异。
--stat 显示每次更新的文件修改统计信息。
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。
--graph 显示 ASCII 图形表示的分支合并历史。
--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
以及如何从远程仓库 拉数据下来或者推数据上去
使用图形化工具查阅提交历史
相当于 git log 命令的可视化版本,
在项目工作目录中输入 gitk 命令后,就会启动,上半个窗口显示的是历次提交的分支祖先图谱,下半个窗口显示当前点选的提交对应的具体差异。


远程仓库的使用

查看当前的远程库
查看当前配置有哪些远程仓库,可以用 git remote 命令,它会列出每个远程库的简短名字。
在克隆完某个项目后,至少可以看到一个名为 origin 的远程库,Git 默认使用这个名字来标识你所克隆的原始仓库:
$ git clone git://github.com/schacon/ticgit.git
Initialized empty Git repository in /private/tmp/ticgit/.git/
remote: Counting objects: 595, done.
remote: Compressing objects: 100% (269/269), done.
remote: Total 595 (delta 255), reused 589 (delta 253)
Receiving objects: 100% (595/595), 73.31 KiB | 1 KiB/s, done.
Resolving deltas: 100% (255/255), done.
$ cd ticgit
$ git remote
origin
显示对应的克隆地址
$ git remote -v
origin  git://github.com/schacon/ticgit.git
有多个远程仓库,此命令将全部列出。比如在我的 Grit 项目中,可以看到:
$ cd grit
$ git remote -v
bakkdoor  git://github.com/bakkdoor/grit.git
cho45     git://github.com/cho45/grit.git
defunkt   git://github.com/defunkt/grit.git
koke      git://github.com/koke/grit.git
origin    git@ github.com:mojombo/grit.git

添加远程仓库
要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,运行 git remote add [shortname] [url]:
clone克隆就是默认名字为origin远程仓库名的远程仓库。
$ git remote add pb git://github.com/paulboone/ticgit.git


从远程仓库抓取数据
要抓取所有 远程仓库 有的,但本地仓库没有的信息,可以运行 git fetch pb:
fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。
$ git fetch [remote-name]
自动抓取数据下来,然后将远端分支自动合并到本地仓库中当前分支。
git pull 命令
在跟踪分支里运行 git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。
$ git pull


推送数据到远程仓库
要同别人分享目前的成果,可以将本地仓库中的数据推送到远程仓库。实现这个任务的命令很简单: git push [remote-name] [branch-name]。
如果要把本地的 master 分支推送到origin 服务器上,可以运行下面的命令:(克隆操作会自动使用默认的 master 和 origin 名字)
$ git push origin master
条件:只有在所克隆的服务器上有写权限,或者同一时刻没有其他人在推数据,这条命令才会如期完成任务。如果在你推数据前,已经有其他人推送了若干更新,那 你的推送操作就会被驳回。你必须先把他们的更新抓取到本地,合并到自己的项目中,然后才可以再次推送。
跟踪远程分支:从远程分支 checkout 出来的本地分支,称为 跟踪分支
在跟踪分支里输入 git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。
$ git push



查看远程仓库信息
可以通过命令 git remote show [remote-name] 查看某个远程仓库的详细信息,比如要看所克隆的 origin 仓库
$ git remote show origin
它告诉我们
运行 git push 时缺省推送的分支是什么Local branch pushed with 'git push'
哪些远端分支还没有同步到本地New remote branches (next fetch will store in remotes/origin)
哪些已同步到本地的远端分支在远端服务器上已被删除Stale tracking branches (use 'git remote prune')
运行git pull 时将自动合并哪些分支Remote branch merged with 'git pull' while on branch master
运行 git push 时缺省推送的分支是什么Local branch pushed with 'git push'
远程仓库的删除和重命名
可以用 git remote rename 命令修改某个远程仓库在本地的简短名称
$ git remote rename pb paul
移除对应的远端仓库
$ git remote rm paul


分支
可以在不同分支里反复切换,并在时机成熟时把它们合并到一起。而所有这些工作,仅仅需要branch 和 checkout 这两条命令就可以完成。
因为每次提交时都记录了祖先信息(译注:即parent 对象),将来要合并分支时,寻找恰当的合并基础(译注:即共同祖先)的工作其实已经自然而然地摆在那里了,所以实现起来非常容易。
新建一个 testing 分支
$ git branch testing
切换到其他分支,可以执行 git checkout命令(切换分支的时候最好保持一个清洁的工作区域。)
$ git checkout testing
切换回主分支
$ git checkout master
把 HEAD 指针移回到 master 分支,并把工作目录中的文件换成了 master 分支所指向的快照内容。
Git 会把工作目录的内容恢复为检出某分支时它所指向的那个提交对象的快照。它会自动添加、删除和修改文件以确保目录的内容和你当时提交时完全一样。
根据本分支新建并切换到该分支,运行git checkout 并加上 -b 参数:
$ git checkout -b iss53
根据对应分支新建并切换到该分支,(origin/serverfix对应分支的名称,也可为远程分支)
$ git checkout -b serverfix origin/serverfix
删除已合并的分支
$ git branch -d hotfix
删除尚未合并的分支(强制删除)
$ git branch -d testing


分支的管理
给出当前所有分支的清单
$ git branch
查看各个分支最后一个提交对象的信息
$ git branch -v
要从该清单中筛选出你已经(或尚未)与当前分支合并的分支,可以用 --merge 和 --no-merged 选项
查看哪些分支已被并入当前分支(译注:也就是说哪些分支是当前分支的直接上游。)
$ git branch --merged
列表中没有 的分支通常都可以用 git branch -d 来删掉。原因很简单,既然已经把它们所包含的工作整合到了其他分支,删掉也不会损失什么。
查看尚未合并的工作
$ git branch --no-merged
由于这些分支中还包含着尚未合并进来的工作成果,所以简单地用 git branch -d 删除该分支会提示错误,因为那样做会丢失数据


合并
快进(Fast forward):直接祖先(需要合并的分支是需要被合并分支的直接祖先),如果顺着一个分支走下去可以到达另一个分支的话,那么 Git 在合并两者时,只会简单地把指针右移。
非直接祖先:需要合并的分支和需要被合并分支分别在两条分支上,Git 会用两个分支的末端以及它们的共同祖先进行一次简单的三方合并计算。对三方合并后的结果重新做一个新的快照,并自动创建一个指向它的提交对象,它有两个祖先分别指向两条分支。
$ git checkout master
$ git merge iss53
遇到冲突时的分支合并:如果在不同的分支中都修改了同一个文件的同一部分,Git 就无法干净地把两者合到一起
$ git merge iss53
$ git status
Git 作了合并,但没有提交,它会停下来等你解决冲突。要看看哪些文件在合并时发生冲突,可以用 git status 查阅:
任何包含未解决冲突的文件都会以未合并(unmerged)的状态列出。
Git 会在有冲突的文件里加入标准的冲突解决标记,可以通过它们来手工定位并解决这些冲突。
解决冲突的办法无非是二者选其一或者由你亲自整合到一起。
在解决了所有文件里的所有冲突后,运行 git add 将把它们标记为已解决状态(译注:实际上就是来一次快照保存到暂存区域。)。因为一旦暂存,就表示冲突已经解决。
认所有冲突都已解决,也就是进入了暂存区,就可以用 git commit 来完成这次合并提交。
合并远程仓库(远程仓库名/分支名)
$ git merge origin/serverfix


分支的新建与合并
实际工作中大体也会用到这样的工作流程:1. 开发某个网站。 2. 为实现某个新的需求,创建一个分支。 3. 在这个分支上开展工作。
假设此时,你突然接到一个电话说有个很严重的问题需要紧急修补,那么可以按照下面的方式处理:
1. 返回到原先已经发布到生产服务器上的分支。
2. 为这次紧急修补建立一个新分支,并在其中修复问题。
3. 通过测试后,回到生产服务器所在的分支,将修补分支合并进来,然后再推送到生产服务器上。
4. 切换到之前实现新需求的分支,继续工作。
(注)当你在使用分支及合并的时候,一切都是在你自己的 Git 仓库中进行的 — 完全不涉及与服务器的交互。

利用分支进行开发的工作流程(典型的工作模式)
长期分支,工作流水线(经过测试的提交对象集合被遴选到更稳定的流水线)
这么做的目的是拥有不同层次的稳定性:当这些分支进入到更稳定的水平时,再把它们合并到更高层分支中去。
master:仅在 master 分支中保留完全稳定的代码,即已经发布或即将发布的代码。
develop(next):有一个名为 develop 或 next 的平行分支,专门用于后续的开发,或仅用于稳定性测试 — 当然并不是说一定要绝对稳定,不过一旦进入某种稳定状态,便可以把它合并到 master 里。
在确保这些已完成的特性分支(短期分支)能够通过所有测试,并且不会引入更多错误之后,就可以并到主干分支中,等待下一次的发布。
topic:指一个短期的,用来实现单一特性或与其相关工作的分支。
在提交了若干更新后,把它们合并到主干分支,然后删除。
 
远程分支
是对远程仓库中的分支的索引。它们是一些无法移动的本地分支;只有在 Git 进行网络交互时才会更新。远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置。
我们用 (远程仓库名)/(分支名) 这样的形式表示远程分支。
比如我们想看看上次同 origin 仓库通讯时 master 分支的样子,就应该查看 origin/master 分支。
同步远程服务器上的数据到本地。
$ git fetch origin
该命令首先找到 origin 是哪个服务器,从上面获取你尚未拥有的数据,更新你本地的数据库,然后把 origin/master 的指针移到它最新的位置上.

推送本地分支到远程分支
要想和其他人分享某个本地分支,你需要把它推送到一个你拥有写权限的远程仓库。
你创建的本地分支不会因为你的写入操作而被自动同步到你引入的远程服务器上,你需要明确地执行推送分支的操作。
对于无意分享的分支,你尽管保留为私人分支好了,而只推送那些协同工作要用到的特性分支。
运行 git push (远程仓库名) (分支名):
$ git push origin serverfix
取出我在本地的 serverfix 分支,推送到远程仓库的 serverfix 分支中去
$ git push [远程名] [本地分支]:[远程分支]
$ git push origin serverfix:serverfix
上传我本地的 serverfix 分支到远程仓库中去,仍旧称它为 serverfix 分支
$ git push origin serverfix:awesomebranch
通过此语法,你可以把本地分支推送到某个命名不同的远程分支


跟踪远程分支
从远程分支 checkout 出来的本地分支,称为 跟踪分支,跟踪分支是一种和某个远程分支有直接联系的本地分支。
在跟踪分支里输入 git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。
在这些分支里运行 git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。
Git 通常会自动创建一个名为 master 的分支来跟踪 origin/master。这正是 git push 和 git pull 一开始就能正常工作的原因。
跟踪分支
$ git checkout -b [分支名] [远程名]/[分支名]
$ git checkout --track origin/serverfix
为本地分支设定不同于远程分支的名字
$ git checkout -b sf origin/serverfix
你的本地分支 sf 会自动将推送和抓取数据的位置定位到 origin/serverfix 了。

删除远程分支
在服务器上删除 serverfix 分支
$ git push [远程名] :[分支名]
$ git push origin :serverfix

分支的衍合
用衍合的目的:比如某些项目你不是维护者,但想帮点忙的话,最好用衍合:先在自己的一个分支里进行开发,当准备向主项目提交补丁的时候,根据最新的 origin/master 进行一次衍合操作然后再提交,这样维护者就不需要做任何整合工作(如果是merge的话)
衍合的分支还是跟在master后面,不会创建新的分支,而且已经merge到了主分支后面(已经整合好了),所以维护者观看后可以直接merge主分支,或者抛弃这次衍合。
而如果是使用merge的话,你提交的另一个分支,维护者还需要merge到主分支,然后删除这个分支。
实际上是把解决分支补丁同最新主干代码之间冲突的责任,化转为由提交补丁的人来解决。只需根据你提供的仓库地址作一次快进合并,或者直接采纳你提交的补丁。
有了 rebase 命令,就可以把在一个分支里提交的改变移到另一个分支里重放一遍。
$ git checkout experiment
$ git rebase master
衍合也可以放到其他分支进行,并不一定非得根据分化之前的分支。但这需要用 git rebase 的 --onto 选项指定新的基底分支 master:
$ git rebase --onto master server client
取出 client 分支,找出 client 分支和 server 分支的共同祖先之后的变化,然后把它们在 master 上重演一遍
先取出特性分支 server,然后在主分支 master 上重演
git rebase [主分支] [特性分支]
$ git rebase master server
使用 衍合的原则:
一旦分支中的提交对象发布到公共仓库,就千万不要对该分支进行衍合操作。
如果把衍合当成一种在推送之前清理提交历史的手段,而且仅仅衍合那些尚未公开的提交对象,就没问题。
如果衍合那些已经公开的提交对象,并且已经有人基于这些提交对象开展了后续开发工作的话,就会出现叫人沮丧的麻烦。




专业词汇意思:
checkout:Checkout a branch or paths to the working tree(切换到其他分支)
Trunk:软件开发过程中的主线,开发时版本存放的目录,即在开发阶段的代码都提交到该目录上,保存了从版本库建立到当前的信息。
Branches:软件开发过程中的分支,发布版本存放的目录,即项目上线时发布的稳定版本存放在该目录中,保存了从版本库的某一特定点(不一定是版本库建立时)到当前的信息。
分支主要用于在不影响Trunk其它用户情况下进行一些关于新功能的探索性或实验性的开发,待新功能完善后它也可以合并到Trunk中。
Tags
stage
rebase:衍合
commit:已暂存的文件,staged的文件,下次提交会一并记录到仓库。
committed:表示该文件已经被安全地保存在本地数据库中了, Git 目录中保存着的特定版本文件,就属于已提交状态。
modified:已修改表示修改了某个文件,但还没有提交保存,如果自上次取出后,作了修改但还没有放到暂存区域,就 是已修改状态。
staged:已暂存表示把已修改的文件放在下次提交时要保存的清单中,如果作了修改并已放入暂存区域,就属于已暂存状态;
working directory:Git 的工作目录,从 Git 目录中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。接下来就可以在工作目录中对这些文件进行编辑。
staging area:暂存区域,暂存区域只不过是个简单的文件(索引文件),一般都放在 Git 目录中。
git directory(repository,Git 目录):本地仓库,该目录非常重要,每次克隆镜像仓库的时候,实际拷贝的就是这个目录里面的数据。
git clone 出来的话,就是其中 .git 的目录;如果git clone --bare 的话,新建的目录本身就是 Git 目录。它是 Git 用来保存元数据和对象数据库的地方。
Git 工作流程:1. 在工作目录中修改某些文件。 2. 对修改后的文件进行快照,然后保存到暂存区域。 3. 提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。
本地版本控制系统:诸如 rcs
集中化的版本控制系统,简称 CVCS:诸如 CVS,Subversion 以及 Perforce 等。可以在一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。
分布式版本控制系统,简称 DVCS:像 Git,Mercurial,Bazaar 以及 Darcs 等.客户端并不只提取最新版本的文件快照,而是把原始的代码仓库完整地镜像下来。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜 像出来的本地仓库恢复。因为每一次的提取操作,实际上都是一次对代码仓库的完整备份(见图 1-3)。
merge:Join two or more development histories together
pull:Fetch from and merge with another repository or a local branch
push:Update remote refs along with associated objects
tracking branch:从远程分支 checkout 出来的本地分支,称为 跟踪分支
Pull Request:在派生项目中创建的提交,可以非常方便地利用GitHub的Pull Request工具向原始项目的维护者发送Pull Request。

获取帮助:git help or git help config or git --help or man git-
glob 模式:所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。星号(
)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符(这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c);问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符,表示所有在这两个字符范围内的都可以匹配(比如[0-9] 表示匹配所有 0 到 9 的数字)。

--pretty=format常用的格式占位符写法及其代表的意义
选项   说明
%H  提交对象(commit)的完整哈希字串
%h  提交对象的简短哈希字串
%T  树对象(tree)的完整哈希字串
%t  树对象的简短哈希字串
%P  父对象(parent)的完整哈希字串
%p  父对象的简短哈希字串
%an 作者(author)的名字
%ae 作者的电子邮件地址
%ad 作者修订日期(可以用 -date= 选项定制格式)
%ar 作者修订日期,按多久以前的方式显示
%cn 提交者(committer)的名字
%ce 提交者的电子邮件地址
%cd 提交日期
%cr 提交日期,按多久以前的方式显示
%s  提交说明




idea
绿色:staged 提交后新增加的文件,并且加入了跟踪,但未提交,已暂存状态,如果此时提交,那么该文件此时此刻的版本将被留存在历史记录中
红色:未被跟踪的文件,提交后增加新文件而未加入跟踪untracked
蓝色:已经修改的文件,modified
灰色:未被修改的文件