Git 常用操作

来源:互联网 发布:复制淘宝口令没反应 编辑:程序博客网 时间:2024/06/05 08:55
# 简介

首先,这并不是一篇关于Git基本操作的分享,在看它之前你一要确信自己明白Git的简单操作与版本库、分支等基本概念。虽然小媛混迹Git有段时日,但是渐渐发现git add和git commit已经渐渐不能满足协作开发的需求,于是整理出一些在使用时会接触的到进阶操作,供后人敬仰,哦不,观赏。

ps: 因为各种原因图片未正常显示。


### 版本回退 reset

`git reset --hard commit_id`

HEAD指向当前版本,所以如果你要回退到上一个提交的版本时可以使用`git reset --hard HEAD~`,回退到上n个版本的时候也可以使用`git reset --hard HEAD~n`,当然如果你不是记忆很好的话可以使用`git log`命令查看最近提交的所有版本的`commit_id`,然后找到你要回退的那一个版本对应的`commit_id`,使用`git reset --hard commit_id`命令回退。

操作:

我先使用`git log`把我当前的所有提交显示出来,如下:

![](media/14494585670894/14590662264925.jpg)

当前的HEAD是e5534,我准备回退到806dcc那次提交,于是我使用`git reset --hard HEAD~`,如下:

![](media/14494585670894/14590664323484.jpg)

它提示我已经切换到上一次提交,当前HEAD指针指向的就是806dcc。

但是如果版本回退完我突然想找回原来的版本e5534怎么办呢。

首先我们需要找到当年的那个`commit_id`(装作我不知道它是e5534),于是我试了下`git log`,如下:

![](media/14494585670894/14590666405032.jpg)

并没有当年的`commit_id`,因为git log输出的`commit_id`都是距离当前HEAD最近的提交的所有的`commit_id`,所以我们要使用`git reflog`,git reflog是记录了你所有操作的`commit_id`,我们轻松的找到了要退版本的`commit_id`为e5334:

![](media/14494585670894/14590668360252.jpg)

然后使用`git reset --hard e533474`

![](media/14494585670894/14590670088945.jpg)

哇哈哈,又回来啦!

其实Git中HEAD指向的就是当前的版本,当你进行版本回退等操作时,改变只是HEAD指针的指向,下面的图很好的说明了我们刚刚的操作:

![](media/14494585670894/14590674274582.jpg)

### 合并分支 merge

在Git中有一个主分支master,当你创建版本库的时候他就自动生成了,他像一条时间线,上文中说过HEAD指向当前版本,也就是当前提交,但其实HEAD指向的是master,master直接指向提交,如图:

![](media/14494585670894/14590688517969.jpg)

当我们创建新的分支develop的时候,Git会新建一个develop指针指向master,再将HEAD指针指向develop。当我们在develop上面进行操作的时候并提交的时候,develop指针不断向前移动,master指针原地不动,当我们在develop的开发全部完成时想把这部分功能合并到master时就要切换到master分支,然后使用`git merge develop`命令,这部分的操作如图:

初始状态:

![](media/14494585670894/14590694723586.jpg)

git branch develop 

![](media/14494585670894/14590694897780.jpg)

在develop分支上进行开发后,develop:  git commit -m "develop 开发完成"

![](media/14494585670894/14590695739112.jpg)

master: git merge develop

![](media/14494585670894/14590696416639.jpg)

当本地master落后远程的master分支时,合并分支可能有冲突,解决完有冲突的文件再`git add .``git commit -m "XXX"`就可以了。

上文中分支合并以master与develop为例,其他情况对号替换就好啦。

### 合并分支 rebase

因为上文中的merge会把你的sourceTree搞成这样:

![](media/14494585670894/14590736138938.jpg)

所以作为一个强加强迫症的程序媛是拒绝的,那我们怎么办呢~ rebase来了,它可以避免merge时屎一样的交叉~

当你在主分支拉下分支开发之后,你的队友在主分支又提交了一次更新,于是远程就变成了如下图的origin,但是你还停留在最初的起点!这时候你开发完了需要把你开发的功能并到主分支去。

![](media/14494585670894/14590754646435.jpg)

于是你想到了merge,你可以用pull把远程分支拉下来,然后使用merge把更新后的远程分支和你的开发分支进行合并,解决冲突巴拉巴拉,然后就成了下图。

![](media/14494585670894/14590756698026.jpg)

我们又一次回忆起了那个屎一样的merge图。如果分支很多的话,在sourceTree上这是非常难看的,我们需要一个简洁大气的方式。

你可以这样做:
mywork: git rebase origin
解决冲突
git add .
git rebase --continue

然后就成了下面这样:

![](media/14494585670894/14590759181553.jpg)

然后再把你原来的开发分支删除,如图:

![](media/14494585670894/14590761156793.jpg)

结束啦!

### 合并分支 cherry pick

cherry pick 是将某一次commit应用到某分支作为一次提交。先切使用git log,找到要合并的那次提交,复制`commit_id`,切换到正确的要合并到的分支,使用git cherry-pick commit_id,然后是使用git status解决冲突,再用git add .和git commit(无注释),提交。

![](media/14494585670894/14590737605050.jpg)

(1) 在A分支最后一次commit上进行cherry pick到B分支,相当于在B分支上加入了A分支上最后的commit的内容并作为在B分支上的一次提交。适用于开发feature、bigfix的情况,直接并入develop分支。
(2) 在更新后的B分支的B·部分新建分支A·,将在旧的B分支上开出来的A分支的最后一次提交cherry pick 到A·分支上,并提交。适用于开发mvp版本时,主线版本落后的情况

### 暂存现场 stash

当你正在develop分支开心的开发新功能时,突然收到指令需要紧急修复一个Bug,但是这时候功能只开发了一半,还不能commit怎么办,这时候你可以使用`git stash`,将现在的工作保存下来,然后新开分支去修复Bug,结束后回到develop分支使用`git stash list`,你就可以看到你刚刚暂存的进度,然后是使用`git stash apply`进行恢复,但此时stash里面的内容并不被删除,你还要使用`git stash drop`来删除stash里面的内容,所以为了一劳永逸直接使用`git stash pop`命令就好啦,恢复完事stash内容也被删除啦~

### 重写历史

通俗的说就是把多次本地commit压缩为一次commit(未推到远程仓库)

1. 初始SourceTree:

![](media/14494585670894/14590734295389.jpg)

我们要将前四条commit合并为一条,选中前四条提交中最早的提交的上一次提交,获得它的`commit_id`值。

2. 使用命令: git rebase –i commit_id

![](media/14494585670894/14590734550346.jpg)

3. 我们将后三条提交前面的pick全部改为squash

![](media/14494585670894/14590734674860.jpg)

4. 回到SourceTree,三次commit已经被合并为一次提交。

![](media/14494585670894/14590734799579.jpg)

### 参考链接
这是个非常好的教程[Pro Git中文版](http://git.oschina.net/progit/)
http://git.oschina.net/oschina/git-osc/wikis/Home
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013744142037508cf42e51debf49668810645e02887691000 
0 0