git 个人手册(持续更新)

来源:互联网 发布:linux mount命令使用 编辑:程序博客网 时间:2024/06/09 08:34

git 个人手册

git分布式优势

分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,嗷方便。

创建版本库

首先创建版本所在文件目录

$ mkdir learngit$ cd learngit

第二,利用git init命令创建仓库

$ git init

版本库的跟踪对象

所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等

Git存储结构

git repository

区分指针:其中HEAD 指向 当前分支的commit 版本,Index 指向 staged 版本

提交流程:第一次修改 -> git add -> 第二次修改 -> git add -> git commit

提交修改到暂存区

$ git add readme.txt

git add 可以一次性add多个文件

$ git add file2.txt file3.txt

提交修改到存储区

$ git commit -m "wrote a readme file"

跳过git add直接提交的方法

$ git commit -a -m "wrote a readme file"

-m 后面加入注释

查看仓库当前状态

$ git status

或者使用简写

$ gst

查看文件的改动(Need More)

比较的工作目录(Working tree)和暂存区域快照(index)之间的差异

$ git diff

显示工作版本(Working tree)和HEAD的差别

$ git diff HEAD

查看index file与commit的差别的。

$ git diff --cached

git diff 输出符号

diff --git a/readme.txt b/readme.txtindex 46d49bf..9247db6 100644--- a/readme.txt+++ b/readme.txt@@ -1,2 +1,2 @@-Git is a version control system.+Git is a distributed version control system. Git is free software.

No.1 表示结果为git格式的diff。进行比较的是,a版本的readme.txt(即变动前)和b版本的readme.txt(即变动后)。

No. 2 表示两个版本的git哈希值(index区域的46d49bf对象,与工作目录区域的9247db6对象进行比较),最后的六位数字是对象的模式(普通文件,644权限)。

No.3 表示进行比较的两个文件。 “—”表示变动前的版本,”+++”表示变动后的版本。

No.4 差异按照差异小结进行组织,每个差异小结的第一行都是定位语句,由@@开头,@@结尾。 “-1,2”中“-”表示第一个文件,“1”表示第一行,“2”表示连续的2行。合在一起,就表示下面是第一个文件从第1行开始的连续2行。“+1,2”表示第二个文件的从第1行开始连续的2两行。git diff采用的是这样的合并格式

No.5 往下是具体的变动。它将两个文件的上下文,合并显示在一起,所以叫做”合并格式”。每一行最前面的标志位,空表示无变动,-开头的行,是只出现在源文件中的行,+开头的行,是只出现在目标文件中的行。

查看更改日志

$ git logcommit 3628164fb26d48395383f8f31179f24e0882e1e0Author: Michael Liao <askxuefeng@gmail.com>Date:   Tue Aug 20 15:11:49 2013 +0800    append GPLcommit ea34578d5496d7dd233c827ed32a8cd576c5ee85Author: Michael Liao <askxuefeng@gmail.com>Date:   Tue Aug 20 14:53:12 2013 +0800    add distributedcommit cb926e7ea50ad11b8f9e909c05226233bf755030Author: Michael Liao <askxuefeng@gmail.com>Date:   Mon Aug 19 17:51:55 2013 +0800    wrote a readme file

简化输出

$ git log --pretty=oneline3628164fb26d48395383f8f31179f24e0882e1e0 append GPLea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributedcb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file

每个commit都有自己的SHA1值作为自己的ID,此命令常常用于查询commit ID 以用于版本回退。log从上到下依次为从新到旧的顺序。

查询文件更改历史

$ git blame <fileName>

输出时间、作者以及修改的详细内容

查询对commit的详细更改信息

$ git show <commit-id>

版本回退与撤销回退

确定当前版本

在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

回退

以上面为例子,将版本回退到上一个版本

$ git reset --hard HEAD^

同时,工作区内容也将被改为上个版本的内容

仅撤销某个commit而保留其他所有更改

利用revert进行操作,可以撤销某个commit,不同于reset的是,其他所有的commit会被保留,且这次撤销操作也会被保存为一个commit进行提交

$ git revert <commit-id>

撤销回退

找到新版本的commit ID

通过查找每次命令记录来确定ID

$ git reflogea34578 HEAD@{0}: reset: moving to HEAD^3628164 HEAD@{1}: commit: append GPLea34578 HEAD@{2}: commit: add distributedcb926e7 HEAD@{3}: commit (initial): wrote a readme file

根据ID撤销回退

$ git reset --hard 3628164

快速回退原理

利用HEAD指针来回在不同版本中穿梭
head_one
head_two

丢弃修改

丢弃工作区的修改

$ git checkout -- readme.txt

如果 readme.txt 没有放到暂存区,那么就撤销到修改前的状态,和版本库态相同

如果 reamd.txt 已经放到了暂存区,那么就撤销修改到暂存区的状态

丢弃已经添加到暂存区的修改

$ git reset HEAD readme.txt

把暂存区的修改撤销掉(unstage),重新放回工作区

删除文件

删除版本库文件

$ git rm temp.txt$ git commit -m "remove temp.txt"

注意:工作区的文件也会被删除。撤销删除操作可以使用git reset –hard 命令

远程GitHub仓库

No.1 首先,在GitHub网页上建立仓库

No.2 生成SSH KEY,可以在仓库的根目录下进行操作,但请务必注意编写.gitignore防止密钥上传

$ ssh-keygen -t rsa -C "youremail@example.com"

No.3 确认ssh-agent是否已经开启

$ eval "$(ssh-agent -s)"Agent pid 59566

No.4 添加private key 到 ssh-agent 中

$ ssh-add ~/.ssh/id_rsa

No.5 添加public key到GitHub去

No.6 与关联本地仓库关联

$ git remote add origin git@github.com:USERNAME/learngit.git

关联后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

No.7 本地库内容上传到远程关联端

$ git push -u origin master

把当前分支推送到远程origin(远程端库对应到本地的名字,但是再GitHub上这个库有自己的名字)库master分支中。-u参数同时把这本地远程两个分支进行了关联。

把远程库clone到本地

git clone git@github.com:USERNAME/REPOSITORYNAME.git

分支管理

创建分支

创建一个dev分支,git checkout命令加上-b参数表示创建并切换

$ git checkout -b dev

等价于下面两条命令

$ git branch dev$ git checkout dev

合并分支

$ git merge dev

有时会出现Fast-forward信息,表示这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快,如图所示
fast-forward

删除分支

$ git branch -d dev

解决冲突(Conflict)

当两个分支同时对同几行内容进行了修改,在合并分支时就会出现问题,并在文件中有所显示

<<<<<<< HEADCreating a new branch is quick & simple.=======Creating a new branch is quick AND simple.>>>>>>> feature1

Git用<<<<<<<,=======,>>>>>>>标记出不同分支的内容,我们修改如下后保存:

Creating a new branch is quick and simple.


再提交,则master和feature1的分支情况如下

fix_conflict

实质上,解决冲突就是在feature1分支的更改无法提交到master分支上时,手动更改无法合并的部分并commit,上面的例子中,最终将冲突部分改为“quick and simple”并commit,但是feature1的readme.txt依旧为“quick AND simple”,并没有受到影响。解决冲突后如果继续使用“git merge feature1”则会提示“Already up-to-data”,feature1分支的“quick AND simple”也并没有和到master分支上去,如上图绿色的线所示。

查看分支合并图

git log --graph

查看简易版的合并图

git log --graph --pretty=oneline

分支策略

Bug分支

命名

一般由isssue + BUGID的方式命名,当接到一个修复一个代号101的bug的任务时,就可以创建一个分支issue-101来修复它。

方法

No.1 存储现场,保护没有提交的工作区(如果没有更改则忽略此步)

$ git stash

No.2 确定需要修复的分支,修复谁,就在谁身上创建一个issue分支

$ git checkout -b issue-101

No.3 在issue分支上修改bug并提交

$ git add readme.txt $ git commit -m "fix bug 101"

No.4 切换到master并合并issue

$ git checkout master$ git merge --no-ff -m "fix bug 101" issue-101

No.5 还原工作现场


还原现场并手动删除现场信息

$ git stash apply$ git stash drop

还原现场并自动删除存储的信息

$ git stash pop

附加

查看stash的内容

$ git stash list

恢复指定的stash内容

$ git stash apply stash@{0}

feature分支

每增加一个新的功能,最好就建立一个新的feature分支,防止搞乱主分支

远程仓库和分支管理

查看远程仓库信息

简版,仅显示远程分支的名称

$ git remoteorigin

详细版本,显示显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

$ git remote -vorigin  git@github.com:michaelliao/learngit.git (fetch)origin  git@github.com:michaelliao/learngit.git (push)

推送分支

推送分支,把该分支上的所有本地提交推送到远程库

$ git push <远程主机名> <本地分支名>:<远程分支名>

如果省略远程分支名,则表示将本地分支推送与之存在”追踪关系”的远程分支(通常两者同名),如果该远程分支不存在,则会被新建。

$ git push origin master表示将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建。

如果当前分支只有一个追踪分支,那么主机名都可以省略。

一般先抓取分支解决可能的冲突再提交

###抓取分支取回远程主机某个分支的更新,再与本地的指定分支合并
$ git pull <远程主机名> <远程分支名>:<本地分支名>

如果远程分支是与当前分支合并,则冒号后面的部分可以省略。

如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名。

–rebase的使用

$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

加上 rebase 的意思是

  1. 把本地 repo. 从上次 pull 之后的变更暂存起來
  2. 恢复到上次 pull 时的状态
  3. 合并远端的变更到本地
  4. 最后再合并刚刚暂存下來的本地变更

分支间获取commit

在一个分支上应用另一个分支上的commit

$ git checkout <The branch needed to be changed>$ git cherry-pick <commit-id>

子模块更新

建议先使用

$ git pull --rebase

再对子模块进行更新

$ git submodule sync$ git submodule init$ git submodule updata

sync表示:与子模块的远程URL配置进行同步
init表示:初始化子模块,把子模块名称与对应的URL复制到.git/config中去
update表示:从远程clone丢失的子模块以及从刷新本地的子模块

参考文献

  1. http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
  2. http://www.yiibai.com/git/
0 0