git常用操作

分支管理

分支的概念 

分支是用来标记特定代码的提交,每一个分支通过SHA1sum值来标识,所以对分支的操作是轻量级的,你改变的仅仅是SHA1sum值。

如下图所示,当前有2个分支,A,C,E属于master分支,而A,B,D,F属于dev分支。

A----C----E(master)
 \
  B---D---F(dev)

它们的head指针分别指向E和F,对上述做如下操作:

git checkout master  //选择or切换到master分支
git merge dev        //将dev分支合并到当前分支(master)中

合并完成后:

A---C---E---G(master)
 \         /
  B---D---F(dev)

现在ABCDEFG属于master,G是一次合并后的结果,是将E和F的代码合并后的结果,可能会出现冲突。而ABDF依然属于dev分支。可以继续在dev的分支上进行开发:

A---C---E---G---H(master)
 \         /
  B---D---F---I(dev)

分支常用命令

查看本地分支:git branch

git查看所有本地仓库分支和远程分支:git branch -al

 注:a,前面带有remotes的分支都是远程分支。

         b,星号(*)表示当前所在分支。

创建本地分支:git branch <name>

切换分支:git checkout <name>

创建+切换分支:git checkout -b <name>

拉取远程分支并创建本地分支

方法一
使用如下命令:

git checkout -b 本地分支名x origin/远程分支名x

使用该方式会在本地新建分支x,并自动切换到该本地分支x。

采用此种方法建立的本地分支会和远程分支建立映射关系。

方式二
使用如下命令:

git fetch origin 远程分支名x:本地分支名x

使用该方式会在本地新建分支x,但是不会自动切换到该本地分支x,需要手动checkout。

采用此种方法建立的本地分支不会和远程分支建立映射关系。

删除本地分支:git branch -D <name>  

提交本地分支到远程分支:git push origin <name>:<name>

注:冒号前为本地分支名称,冒号后为远程分支名称,即推送本地的(冒号前面的)分支到远程origin的(冒号后面的)分支(没有会自动创建)

删除远程分支:git push origin --delete <name>

重命名本地分支:git branch -m <old_name> <new_name>

合并分支:git merge <name>

checkout 切换到master,然后将所需的分支并入,注意:切换过程中,暂缓区或工作目录存在未提交的修改,可能会造成冲突的的发生,所以尽量保持工作区的清洁.

git checkout master

git merge test_branch (即将rest_branch分支合并到master分支)

标签管理

创建标签:git tag -a 'tag_name' -m 'tag_info'

git tag -a 'Release_1_0' -m 'Tagged basic string operation code' HEAD

如果要标记特定提交,则使用相应的COMMIT ID而不是HEAD指针。

使用以下命令将标签推送到远程存储库:

git push origin tag Release_1_0

查看标签:git tag -l

查看标签详细信息:git show Release_1_0

删除标签

删除本地标签:git tag -d Release_1_0

删除远程标签:git push origin :Release_1_0

git pull 和 git fetch 用法和区别

可以简单的概括为:

git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。

git pull 则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch + git merge,这样可能会产生冲突,需要手动解决。

原理细节可参考:

https://zhuanlan.zhihu.com/p/123370920 详解git pull和git fetch的区别

https://blog.csdn.net/a19881029/article/details/42245955  git fetch和git pull之间的区别

git fetch 用法

git fetch 命令:

$ git fetch <远程主机名> //这个命令将某个远程主机的更新全部取回本地

如果只想取回特定分支的更新,可以指定分支名:

$ git fetch <远程主机名> <分支名> //注意之间有空格

最常见的命令如取回origin 主机的master 分支:

$ git fetch origin master

取回更新后,会返回一个FETCH_HEAD ,指的是某个branch在服务器上的最新状态,我们可以在本地通过它查看刚取回的更新信息:

$ git log -p FETCH_HEAD

可以看到返回的信息包括更新的文件名,更新的作者和时间,以及更新的代码(红色[删除]和绿色[新增]部分)。

我们可以通过这些信息来判断是否产生冲突,以确定是否将更新merge到当前分支。 

git pull 用法

前面提到,git pull 的过程可以理解为:

git fetch origin master //从远程主机的master分支拉取最新内容 
git merge FETCH_HEAD    //将拉取下来的最新内容合并到当前所在的分支中

即将远程主机的某个分支的更新取回,并与本地指定的分支合并,完整格式可表示为:

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

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

$ git pull origin next

git生成patch

git format-patch

$ git format-patch HEAD^                 #生成最近的1次commit的patch

$ git format-patch HEAD^^               #生成最近的2次commit的patch

$ git format-patch HEAD^^^              #生成最近的3次commit的patch

$ git format-patch HEAD^^^^                  #生成最近的4次commit的patch

$ git format-patch <r1>..<r2>                                              #生成两个commit间的修改的patch(包含两个commit. <r1>和<r2>都是具体的commit号)

$ git format-patch -1 <r1>                                                   #生成单个commit的patch

$ git format-patch <r1>                                                       #生成某commit以来的修改patch(不包含该commit)

$ git format-patch --root <r1>               #生成从根到r1提交的所有patch

git使用patch

git am

$ git apply --stat 0001-limit-log-function.patch         # 查看patch的情况

$ git apply --check 0001-limit-log-function.patch        # 检查patch是否能够打上,如果没有任何输出,则说明无冲突,可以打上

(注:git apply是另外一种打patch的命令,其与git am的区别是,git apply并不会将commit message等打上去,打完patch后需要重新git add和git commit,而git am会直接将patch的所有信息打上去,而且不用重新git add和git commit,author也是patch的author而不是打patch的人)

$ git am 0001-limit-log-function.patch                                # 将名字为0001-limit-log-function.patch的patch打上

$ git am --signoff 0001-limit-log-function.patch                  # 添加-s或者--signoff,还可以把自己的名字添加为signed off by信息,作用是注明打patch的人是谁,因为有时打patch的人并不是patch的作者

$ git am ~/patch-set/*.patch             # 将路径~/patch-set/*.patch 按照先后顺序打上

$ git am --abort                                                                   # 当git am失败时,用以将已经在am过程中打上的patch废弃掉(比如有三个patch,打到第三个patch时有冲突,那么这条命令会把打上的前两个patch丢弃掉,返回没有打patch的状态)

$ git am --resolved                                                             #当git am失败,解决完冲突后,这条命令会接着打patch

解决打patch冲突

如果打Patch的过程中发生了冲突(conflicts),怎么办?

解决patch冲突的过程是:

如果不想打这一系列patch了,直接:git am --abort。

如果还想打, 有两种解决方案:

方案一(个人推荐):

(1) 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply --reject <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch

(2) 根据.rej文件,通过编辑该patch文件的方式解决冲突。

(3) 废弃上一条am命令已经打了的patch:git am --abort

(4) 重新打patch:git am ~/patch-set/*.patchpatch

方案二:

(1) 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply --reject <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch

(2) 根据.rej文件,通过编辑发生冲突的code文件的方式解决冲突。

(3) 将该patch涉及到的所有文件(不仅仅是发生冲突的文件)通过命令git add <file_name>添加到工作区中

(4) 告诉git冲突已经解决,继续打patch: git am --resolved (git am --resolved 和 git am --continue是一样的)

分析:方案一和方案二主要区别是解决冲突的方法不一样。方案一是通过编辑patch文件的方式解决冲突,方案二十通过编辑冲突code文件的方式解决冲突。这两种方案区别比较大:经过实验,核心区别在于,方案二无法验证冲突有没有切实的解决。即使你在方案二的第二步乱改一通,也能“打完”发生冲突的patch(并没有检测修改后的code文件跟patch期望的是否相同)。因此,如果采用方案二,那么再解决code文件冲突后,需要人工去确认修改的正确性。

Git 上多次commit 合并成一个 patch

对于一个test 工程   git log 看其提交的过程:
commit 9fdd76eb5fd06b1b7f2af6800dc13e51099c40d9  
Author: ShichaoXu <gudujianjsk@gmail.com>  
Date:   Tue Dec 31 17:13:24 2013 +0800  
  
    printf hello world  
  
commit a648e0564c0802267edc774c010956b343e6a844  
Author: ShichaoXu <gudujianjsk@gmail.com>  
Date:   Tue Dec 31 17:12:22 2013 +0800  
  
    add second line  
  
commit 808d68dee51db0c3e64301f43be3c8b8a3808f5a  
Author: ShichaoXu <gudujianjsk@gmail.com>  
Date:   Tue Dec 31 17:11:58 2013 +0800  
  
    add first line  
  
commit 3c5fef11eb9389f3575f8a11dda2deb3b79aa668  
Author: ShichaoXu <gudujianjsk@gmail.com>  
Date:   Tue Dec 31 17:11:16 2013 +0800  
  
    add test.c  


经过第四次commit之后文件内容如下:

#include <stdio.h>  
  
int main()  
{  
    printf("hello world\n");  
    return 0;  
}  

首先创建一个新的分支 dev (原来分支是master)

$ git checkout -b dev  
Switched to a new branch 'dev'  

$ git branch   
* dev  
  master  

再使用git reset 命令彻底回退到某个版本,这里回退到第一次commit之后:

$ git reset --hard 3c5fef11eb9389f3575f8a11dda2deb3b79aa668  
HEAD is now at 3c5fef1 add test.c  

此时git log 发现后面3次commit已经没有了:

$ git log   
commit 3c5fef11eb9389f3575f8a11dda2deb3b79aa668  
Author: ShichaoXu <gudujianjsk@gmail.com>  
Date:   Tue Dec 31 17:11:16 2013 +0800  
  
    add test.c  

同时first.c 文件内容也为空。

再使用git merge:

$ git merge master --squash  
Updating 3c5fef1..9fdd76e  
Fast-forward  
Squash commit -- not updating HEAD  
 first.c |    7 +++++++  
 1 file changed, 7 insertions(+)  

--squash选项的含义是:本地文件内容与不使用该选项的合并结果相同,但是不保留待合并分支上的历史信息,也不提交、不移动HEAD,因此需要一条额外的commit命令。其效果相当于将another分支上的多个commit合并成一个,放在当前分支上,原来的commit历史则没有拿过来。
   判断是否使用--squash选项最根本的标准是,待合并分支上的历史是否有意义。


再编辑一下commit信息:


$ git commit -m "add a program--printf hello world"  
[dev 50dc073] add a program--printf hello world  
 1 file changed, 7 insertions(+)  

git log :

$ git log   
commit 50dc07351f136f5855b0d0ee3078f9192a58838b  
Author: ShichaoXu <gudujianjsk@gmail.com>  
Date:   Tue Dec 31 18:03:31 2013 +0800  
  
    add a program--printf hello world  
  
commit 3c5fef11eb9389f3575f8a11dda2deb3b79aa668  
Author: ShichaoXu <gudujianjsk@gmail.com>  
Date:   Tue Dec 31 17:11:16 2013 +0800  
  
    add test.c  

此时dev 分支的first.c 文件与 master 分支一样。
可以用    git format-patch 制作补丁

$ git format-patch HEAD^  
0001-add-a-program-printf-hello-world.patch  


总结:

1. 基于当前已经修改过的分支 Test  创建新分支 Fix  切换到分支 Fix

2. git log 查看提交记录 

假如当前提交记录为:commit 5

    commit 4

    commit 3

    commit 2

    commit 1

    commit 原始

3. 自己新提交的有五次   使用git reset 命令彻底回退到某个版本 这里回退到commit 原始

git reset --hard 原始

4. git merge Test --squash

5. 再编辑一下commit信息

git commit -m " new message "

6. git log 查看合并好的提交

7. 使用 git format-patch HEAD^ 制作补丁
 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值