Git常用场景下的使用

 

一. Git 基本知识与安装

  以前自己虽然会用 Git,但从来没有系统总结过Git的使用,就借这个机会盘点一下把。

  Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。。。。。。这些东西就不说了,百度即可。

  Git 主要有以下三个区:

  • 工作区:就是你在电脑里能看到的目录。
  • 暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
  • 版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。

   他们的关系如下:

 了解大致关系就行,下面会通过实际演示来掌握Git的使用

 安装的话

  • Linux 一般都会带 Git, 没有的话 输入sudo apt install git 即可
  • Windows 去官网 https://git-scm.com/downloads 下载即可
  • Macos  。。贫穷限制了我的。。0.0 其实也是去官网下载

 

二. 主要场景的使用

 

1. Git 基本功能的使用

 

1.1 最简单的流程

这里我们最简单的git使用的一个流程

先在本地建立一个sse文件夹,将该文件夹作为git仓库,然后使用 git init 命令进行初始化。这时候我们用 git status 可以看到仓库是非常干净的。

crazyliu@DESKTOP-TTUBPSH:~$ mkdir sse
crazyliu@DESKTOP-TTUBPSH:~$ cd sse
crazyliu@DESKTOP-TTUBPSH:~/sse$ ls
crazyliu@DESKTOP-TTUBPSH:~/sse$ git init
Initialized empty Git repository in /home/crazyliu/sse/.git/
crazyliu@DESKTOP-TTUBPSH:~/sse$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

再建立一个read.me文件,并向其中写入first write并保存。这个时候如果再运行git status命令就可看给他提示没有追踪该文件,我们使用 git add命令将其加入暂存区,再次运行 git status,提示暂存区有未提交的change。

crazyliu@DESKTOP-TTUBPSH:~/sse$ touch read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me 
first write
crazyliu@DESKTOP-TTUBPSH:~/sse$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    read.me

nothing added to commit but untracked files present (use "git add" to track)
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   read.me

最后我们运行 git commit -am "<message>" 即可将暂存区的change进行提交到版本库。再运行 git status 可以看到仓库又变得干净了。运行 git log 可以看到我们刚才的那一次提交的信息。

crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "first commit"
[master (root-commit) 663887f] first commit
 1 file changed, 1 insertion(+)
 create mode 100644 read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git status
On branch master
nothing to commit, working tree clean
crazyliu@DESKTOP-TTUBPSH:~/sse$ git log
commit 663887ffb57a0feaf2d4f45b0bfa59f932ec2c9e (HEAD -> master)
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:39:57 2020 +0800

    first commit

 

1.2 版本时光穿梭机

Git的一个重要功能就是在版本之间进行穿梭,现在我们来演示一下。在上面的例子中,我们只有一个commit。为了演示,我们按照上面的做法先给read.me文件加一行second write,提交一次。再给read.me 文件加一行 third write, 提交一次。这样我们的read.me文件就有了3行,总共3次提交。

crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me 
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write
second write
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "second commit"
[master ff82d97] second commit
 1 file changed, 1 insertion(+)
crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write
second write
third write
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "third commit"
[master 1186510] third commit
 1 file changed, 1 insertion(+)
crazyliu@DESKTOP-TTUBPSH:~/sse$ git log
commit 118651050aabde2a59e60100580dc9cf2cbc89a2 (HEAD -> master)
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:52:30 2020 +0800

    third commit

commit ff82d978175d1b240153901d36ae3bfc6cb544e7
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:51:42 2020 +0800

    second commit

commit 663887ffb57a0feaf2d4f45b0bfa59f932ec2c9e
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:39:57 2020 +0800

    first commit

现在我们是在第三次提交也就是third commit 这里,如果我们要回到第一次提交first commit 那里,要怎么操作呢?可以使用这条命令 git reset --hard HEAD^^,其中HEAD指向当前所在的版本,后面加一个^就是前面的一个版本,加两个^^就是往前走两个版本,如果向前走100个版本,则可以用HEAD~100。这时、用 git log 查看日志可以发现的确回到了过去。

crazyliu@DESKTOP-TTUBPSH:~/sse$ git reset --hard HEAD^^
HEAD is now at 663887f first commit
crazyliu@DESKTOP-TTUBPSH:~/sse$ git log
commit 663887ffb57a0feaf2d4f45b0bfa59f932ec2c9e (HEAD -> master)
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:39:57 2020 +0800

    first commit

  那我们要回到刚才 third commit 要怎么办呢?同样是上面的那条命令,只是将 --hard 后面的换成 要去的commit 的id的前几位。要知道这个id可以使用 git reflog 查看穿梭的日志,在其中可以找到third commit 的id前几位为1186510。再次运行 git log 可以看到我们又回到了现在

crazyliu@DESKTOP-TTUBPSH:~/sse$ git reset --hard HEAD^^
HEAD is now at 663887f first commit
crazyliu@DESKTOP-TTUBPSH:~/sse$ git log
commit 663887ffb57a0feaf2d4f45b0bfa59f932ec2c9e (HEAD -> master)
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:39:57 2020 +0800

    first commit
crazyliu@DESKTOP-TTUBPSH:~/sse$ git reflog
663887f (HEAD -> master) HEAD@{0}: reset: moving to HEAD^^
1186510 HEAD@{1}: commit: third commit
ff82d97 HEAD@{2}: commit: second commit
663887f (HEAD -> master) HEAD@{3}: commit (initial): first commit
crazyliu@DESKTOP-TTUBPSH:~/sse$ git reset --hard 1186510
HEAD is now at 1186510 third commit
crazyliu@DESKTOP-TTUBPSH:~/sse$ git log
commit 118651050aabde2a59e60100580dc9cf2cbc89a2 (HEAD -> master)
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:52:30 2020 +0800

    third commit

commit ff82d978175d1b240153901d36ae3bfc6cb544e7
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:51:42 2020 +0800

    second commit

commit 663887ffb57a0feaf2d4f45b0bfa59f932ec2c9e
Author: crazyliu <xxxxxxxxx@qq.com>
Date:   Sun Oct 11 14:39:57 2020 +0800

    first commit

 

1.3 文件的回退

上面我们介绍了在版本之间回退与前进,这个部分我们介绍另一个有用的技巧。有时候我们把文件改的乱七八糟,或者把一些不该提交的东西 add进了暂存区,这时候我们就要用到文件的回退。

比如我们把read.me改的一无是处,但是还没有add进暂存取,然后想回到commit完的样子,但又忘记是啥样了或者很麻烦,就可以使用 git checkout -- <filename>, <filename>是要回退的文件名,注意中间有 - 并且是 --。如回退所有地文件,则用git checkout ., 小心使用,会丢失本地所有修改。运行完上面地命令可以看到成功回退了,又可以愉快地玩耍了。

crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me 
first write
second write
third write
my boss is a stupid fool
my boss is a stupid fool
my boss is a stupid fool
my boss is a stupid fool
my boss is a stupid fool
crazyliu@DESKTOP-TTUBPSH:~/sse$ git checkout -- read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me 
first write
second write
third write

 

 

2. 与远程版本库一起工作

上面介绍了在本地版本库使用的一些git命令,这个部分我们将演示如何连接到远程版本库并一起工作。

2.1 连接到远程仓库

2.1.1本地代码推送到新仓库

上面我们的演示都是在本地的sse仓库进行,这部分演示如何将其推送到github的新仓库上。

我们先在github上建立一个 sse_test 的空仓库,如下所示

          

然后使用 git remote add origin <远程仓库地址> 将远程仓库地址添加进来,<远程仓库地址> 填入你的远程仓库地址。再使用 git push -u origin master 即可将本地代码推送到远程代码库的master分支上。
如 遇到 Permission Denied, 可以参考 https://blog.csdn.net/gdutxiaoxu/article/details/53573399 添加公钥,以后访问也便捷。
crazyliu@DESKTOP-TTUBPSH:~/sse$ git push -u origin master
The authenticity of host 'github.com (13.250.177.223)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,13.250.177.223' (RSA) to the list of known hosts.
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (9/9), 668 bytes | 222.00 KiB/s, done.
Total 9 (delta 0), reused 0 (delta 0)
To github.com:csflyer/sse_test.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
2.1.2 远程仓库代码拷贝到本地

在一个文件夹下使用 git clone <远程仓库地址> 即可将远程仓库代码拷贝到本地,<远程仓库地址> 填入你的远程仓库地址, 这一过程会在本地新建一个仓库用于存放远程仓库代码

crazyliu@DESKTOP-TTUBPSH:~$ git clone git@github.com:csflyer/sse_test.git
Cloning into 'sse_test'...
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 9 (delta 0), reused 9 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), done.
2.1.3 本地代码推送到远程仓库

在 2.1.1中介绍了本地代码推送到远程新仓库,这里介绍如何将本地代码推送到不是新建的远程仓库。

在一般情况下我们使用 git push origin master 命令即可,master 为要推送的分支名,分支可以查看下一小节。这里我们对read.me添加一行fourth write并提交,再使用git push origin master 进行推送即可,如下所示

crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me 
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write
second write
third write
fourth write
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "fourth commit"
[master 8a40181] fourth commit
 1 file changed, 1 insertion(+)
crazyliu@DESKTOP-TTUBPSH:~/sse$ git push origin master
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 267 bytes | 267.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:csflyer/sse_test.git
   1186510..8a40181  master -> master

注意当远程代码库与本地库不一致时,上面的动作会失败,解决办法请参考2.4.1节

 

2.3. 多人协作

上面的1,2小节介绍了单人开发的一个流程,在多人协作开发的情况下,会出现新的问题和情况,这就需要我们改变现有的流程

2.3.1 代码拉取与合并

在多人协作的开发模式下,远程代码库容易与本地库不一致,这个时候需要进行代码拉取与合并,代码拉取就是将最新的远程代码库弄到本地仓库上

为了演示,我们在github上的仓库上修改read.me 为每一句话后加一个分号并提交

               

 

然后我们在本地仓库上编辑read.me 并添加第五行 fifth write 并提交。这个时候本地仓库和远程代码是不一致的,如果我们用 git push origin master 推送会失败

crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me 
crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "fifth commit"
[master 6c815a0] fifth commit
 1 file changed, 1 insertion(+)
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write
second write
third write
fourth write
fifth write;
crazyliu@DESKTOP-TTUBPSH:~/sse$ git push origin master
Warning: Permanently added the RSA host key for IP address '192.30.255.113' to the list of known hosts.
To github.com:csflyer/sse_test.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:csflyer/sse_test.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

这时我们要用 git fetch 拉取远程仓库的代码,再运行git merge 将本地的代码和刚拉取下来的代码合并。为了方便使用,git 有一条命令 git pull,相当于把这两条命令结合起来,这里我们直接运行

razyliu@DESKTOP-TTUBPSH:~/sse$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:csflyer/sse_test
   8a40181..9a150f4  master     -> origin/master
Auto-merging read.me
CONFLICT (content): Merge conflict in read.me
Automatic merge failed; fix conflicts and then commit the result.

可以看到这里直接提示我们 合并的过程中有冲突,需要修改再合并。这里我们运行 git diff 就能看到发生冲突的地方,手动修改完,再commit提交。这个时候运行 git push origin master 就不会报错了

crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write;
second write;
third write;
fourth write;
fifth write;
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "first merge"
[master 24d128f] first merge
crazyliu@DESKTOP-TTUBPSH:~/sse$ git push origin master
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 543 bytes | 271.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:csflyer/sse_test.git
9a150f4..24d128f master -> master

所以在每次向远程代码库推送的时候都应该先git pull, 合并完所有冲突再提交。

 

2.3.2 代码分支

分支顾名思义就是指代码仓库有不同的发展分支或方向。在上面的演示中,我们只用到了一个分支 master,那么我们为什么需要多个分支呢,或者多个分支能解决什么问题呢?

比如,一个软件产品往往会发布多个版本,如正式版,beta版,测试版。不同的人在开发中会分配到不同的任务,有的人负责开发新功能,有的人负责解决bug,多项任务同时推进。那么所有人都向一个分支提交代码,

就会使得多项工作之间的关系错综复杂,代码容易出错,需要更多的经历去维护代码的一致性。而分支的出现就能很好解决这个问题,每人每项任务可以单独在一个分支进行,彼此之间完全不受影响,任务完成时再合并到master分支即可,非常方便

分支常用的命令如下:

  • 创建分支            git branch <branch name>, 其中 <branch name> 为分支的名字
  • 查看所有分支     git branch,显示结果中前面带 * 的为当前所在分支
  • 切换分支            git checkout <branch name>, 其中 <branch name> 为分支的名字
  • 分支合并            git merge <branch name>, 其中 <branch name> 为分支的名字
  • 分支删除            git branch -d <branch name>, 其中 <branch name> 为分支的名字
 
2.3.2.1 基本流程

分支管理的基本流程就是新创建一个分支,开发完之后再合并到其他分支上。

为了演示,我们假定我们的仓库总共需要两个分支,原来的master分支为主分支,新建一个dev分支用来进行开发,开发完再合并到master分支上。

首先我们用 git branch dev 创建 dev 分支,使用 git branch 可以看到创建成功了,且当前处在master分支

crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch dev
crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch
  dev
* master

然后我们进行开发,给read.me文件加一行 write on new branch dev; 并提交

crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me 
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write;
second write;
third write;
fourth write;
fifth write;
write on new branch dev;
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "commit on new branch dev"
[master 5faed18] commit on new branch dev
 1 file changed, 1 insertion(+)

最后我们进行代码合并,先使用 git checkout master 切换到要合并到的分支master上,再使用 git merge dev 合并 dev分支。

crazyliu@DESKTOP-TTUBPSH:~/sse$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
crazyliu@DESKTOP-TTUBPSH:~/sse$ git merge dev
Already up to date.

合并完后 我们可以用 git log --graph 查看合并的log图,因为这里dev分支只是领先一个commit,所以git 直接将HEAD移到了dev分支的最后一个节点,没有出现分叉。最后使用 git branch -d dev删除分支,一次基本的分支合并就完成了

 

crazyliu@DESKTOP-TTUBPSH:~/sse$ git log --graph
* commit 5faed18d5caff886a6286d9698a2ab7c3407efa5 (HEAD -> master)
| Author: crazyliu <xxxxxxxxxx@qq.com>
| Date:   Mon Oct 12 09:50:34 2020 +0800
| 
|     commit on new branch dev
|   
*   commit 24d128ff6f4a58624267dee77dac520a192b3992 (origin/master, dev)
|\  Merge: 6c815a0 9a150f4
| | Author: crazyliu <xxxxxxxxx@qq.com>
| | Date:   Sun Oct 11 19:08:13 2020 +0800
| | 
| |     first merge
| | 
| * commit 9a150f4b6d0bac63f7afdae8135ba1e03f08bce6
| | Author: csflyer <xxxxxxxxxx@qq.com>
| | Date:   Sun Oct 11 18:56:54 2020 +0800
| | 
| |     Update read.me
| | 
* | commit 6c815a0a5758e4fc9892877be35b64cd435dcd7e
|/  Author: crazyliu <xxxxxxxxx@qq.com>
|   Date:   Sun Oct 11 18:59:26 2020 +0800
|   
|       fifth commit
| 
* commit 8a40181344b5f959272693263ee1c96220df395f
| Author: crazyliu <xxxxxxxxx@qq.com>
| Date:   Sun Oct 11 17:00:26 2020 +0800
| 
|     fourth commit
| 
* commit 118651050aabde2a59e60100580dc9cf2cbc89a2
| Author: crazyliu <xxxxxxxxx@qq.com>
| Date:   Sun Oct 11 14:52:30 2020 +0800
| 
|     third commit
| 
* commit ff82d978175d1b240153901d36ae3bfc6cb544e7
| Author: crazyliu <xxxxxxxxx@qq.com>
| Date:   Sun Oct 11 14:51:42 2020 +0800
| 
|     second commit
| 
* commit 663887ffb57a0feaf2d4f45b0bfa59f932ec2c9e
  Author: crazyliu <xxxxxxxxxxx@qq.com>
  Date:   Sun Oct 11 14:39:57 2020 +0800
crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch -d dev
Deleted branch dev (was 24d128f).
crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch
* master
 
2.3.2.2  Git Stash 介绍

上面介绍了在分支进行开发的基本流程。这个部分介绍一个有用的命令 Git Stash,它可以保护我们的现场工作。

为了演示,我们先新建一个 dev 分支,并在 master 分支上修改read.me 添加一行 write on branch master; 但是不 add 也不 commit。

这时我们checkout 到dev 分支查看read.me文件,可以看到read.me也多了这一行。

 

crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch dev
crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch
  dev
* master
crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write;
second write;
third write;
fourth write;
fifth write;
write on new branch dev;
write on branch master;
crazyliu@DESKTOP-TTUBPSH:~/sse$ git checkout dev
M    read.me
Switched to branch 'dev'
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write;
second write;
third write;
fourth write;
fifth write;
write on new branch dev;
write on branch master;

这说明在本地一个编辑会影响另一个分支,add也是一样。那么当我们在一个分支的工作还没做完,还不能commit 的情况下,需要紧急处理一个bug或者别的任务,需要再开一个新的分支来解决,

那么现在手头上的改动就需要先放到某个地方保存起来,等弄完了再恢复现场。而这就是git stash的功能。

为了演示,我们这里先checkout 到master分支,再 git branch -d dev 删掉刚才的分支,并用 git reset --hard HEAD 回退,清理环境。

开始演示,首先我们给read.me添加一行 unfinished job; 表示 还未完成的工作,但不 add 也不 commit 。这个时候接到一个紧急任务,有个bug需要紧急处理。

我们可以用git stash 保存我们目前的环境,运行完命令后可以看到我们的环境非常干净,再去创建分支就不会影响到新分支。Good Job!

crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write;
second write;
third write;
fourth write;
fifth write;
write on new branch dev;
unfinished job;
crazyliu@DESKTOP-TTUBPSH:~/sse$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   read.me

no changes added to commit (use "git add" and/or "git commit -a")
crazyliu@DESKTOP-TTUBPSH:~/sse$ git stash
Saved working directory and index state WIP on master: 5faed18 commit on new branch dev
crazyliu@DESKTOP-TTUBPSH:~/sse$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

这时候我们创建新分支 solve-bug 并chekcout 到该分支。再给read.me添加一行 bug has been solved 表示我们解决了这个bug,并commit。最后切换到master分支,合并刚才的solve-bug分支,再删除solve-bug分支即可。

crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch solve-bug
crazyliu@DESKTOP-TTUBPSH:~/sse$ git checkout solve-bug
Switched to branch 'solve-bug'
crazyliu@DESKTOP-TTUBPSH:~/sse$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ cat read.me
first write;
second write;
third write;
fourth write;
fifth write;
write on new branch dev;
bug has been solved;
crazyliu@DESKTOP-TTUBPSH:~/sse$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/sse$ git commit -am "solve bug"
[solve-bug 905e0a1] solve bug
 1 file changed, 1 insertion(+)
crazyliu@DESKTOP-TTUBPSH:~/sse$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
crazyliu@DESKTOP-TTUBPSH:~/sse$ git merge solve-bug
Updating 5faed18..905e0a1
Fast-forward
 read.me | 1 +
 1 file changed, 1 insertion(+)
crazyliu@DESKTOP-TTUBPSH:~/sse$ git branch -d solve-bug
Deleted branch solve-bug (was 905e0a1).

这样的一个bug处理就完成了,最后使用 git stash pop 就可以恢复修改bug之前工作区的内容啦。注意这里恢复会产生冲突,所以还要按之前的办法将冲突的地方解决好,但暂时可以不commit。

 

2.4 Github Fork + Pull Request

 这部分我们还是以之前的sse_test 仓库为例,用小号fork该仓库,分别对应下面的左图和右图

    

 我们在小号的仓库上修改 read.me文件 添加一行 pull reqeust; 并提交

到原仓库可以看到小号发起的pull reqeust请求,直接进行合并即可。

 这样一个 pull request 流程就完成了,还是挺简单的

 

2.5 其他

上面介绍了 git使用的常用流程与命令,下面介绍其他有用的工具与命令

2.5.1 标签

标签就是给一个commit 取一个名字,让它更直观更简洁。相关命令如下:

  • 创建标签:         git tag < tag name> 对当前分支的最新commit打标签   git tag <tag name> <commit id 前几位> 对当前分支的某个 commit 打标签
  • 查看所有标签:  git tag
  • 查看标签信息:  git show <tag name>
  • 删除标签:            git tag -d <tag name>

因为我们上一个commit 是解决bug的,所以这里演示我们添加一个标签solve-tag。使用 git show solve-tag可以看到标签相关的信息,包括作者,时间,备注,修改内容等等

crazyliu@DESKTOP-TTUBPSH:~/sse$ git tag solve-bug
crazyliu@DESKTOP-TTUBPSH:~/sse$ git tag
solve-bug
crazyliu@DESKTOP-TTUBPSH:~/sse$ git show solve-bug
commit 905e0a1cb011972638a9d65a31a2bb8e8d2803d7 (HEAD -> master, tag: solve-bug)
Author: crazyliu <924105150@qq.com>
Date:   Mon Oct 12 15:11:28 2020 +0800

    solve bug

diff --git a/read.me b/read.me
index 6840e70..1fb465d 100644
--- a/read.me
+++ b/read.me
@@ -4,3 +4,4 @@ third write;
 fourth write;
 fifth write;
 write on new branch dev;
+bug has been solved;

 

2.5.2 git cherry-pick

git cherry-pick是一个不那么常用的命令,但有时候很有用,这里简单介绍下。

在2.3.2.2小节中,我们是直接切换到某个分支修改bug再merge。但如果存在很多分支,同时存在该bug急需解决,又不能合并,我们就不得不一个分支一个分支地改,很浪费时间。

git cherry-pick 可以使得只需在其他分支改好,就能将改动的部分应用到本分支,可以节省很多时间。具体命令为 git cherry-pick <commit id 前几位>,这里就不具体演示了

 

2.5.3 git rebase

多次创建新分支,合并后,log会变得非常乱。类似下图。而git rebase就是帮助我们简化log历史的命令,最简单理解就是美化log的,虽然它和merge命令一样是一种合并的方式.用法就是 git rebase <branch name>,  <branch name>

是分支名,以该分支为基础进行合并。

 以下图为例,C0是最刚开始的状态,C1是修改C0后的提交,以此类推,C4和C3是两个分支,在C5处合并。

使用rebase 就可以将这个log变成一条直线 ,见下图。它删掉了C4节点,将C4的改动部分应用到C3,形成新的节点C4’,上面的C5也不需要了,从而将log历史拉成了一条直线,少了一个节点,变简洁了,也变好看了 0.0,。

 为了演示我们新建一个feature分支,在feature分支的read.me 文件添加一行 feature_content 并提交,在master分支的read.me文件添加一行 master_content 并提交,checkout 到feature分支后, 输入git rebase master会提示冲突,如下

crazyliu@DESKTOP-TTUBPSH:~/test$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: add feature content
Using index info to reconstruct a base tree...
M    read.me
Falling back to patching base and 3-way merge...
Auto-merging read.me
CONFLICT (content): Merge conflict in read.me
error: Failed to merge in the changes.
Patch failed at 0001 add feature content
Use 'git am --show-current-patch' to see the failed patch

Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

所以我们要先解决冲突,解决冲突后将冲突文件git add一下,再输入 git rebase continue 继续变基即可完成。

crazyliu@DESKTOP-TTUBPSH:~/test$ vim read.me
crazyliu@DESKTOP-TTUBPSH:~/test$ git add read.me
crazyliu@DESKTOP-TTUBPSH:~/test$ git rebase --continue
Applying: add feature content
crazyliu@DESKTOP-TTUBPSH:~/test$ git log --graph
* commit 37c38612c712db1d6383d1563e7956eec5d19ef4 (HEAD -> feature)
| Author: crazyliu <xxxxxxxxxx@qq.com>
| Date:   Mon Oct 12 20:31:57 2020 +0800
| 
|     add feature content
| 
* commit 4497702dc92d7af5592606977c106a41c51428e9 (master)
| Author: crazyliu <xxxxxxxxx@qq.com>
| Date:   Mon Oct 12 20:32:29 2020 +0800
| 
|     add master content
| 
* commit 2872564d9f18c395ceb2c6f7f4bbc22845da86c7
  Author: crazyliu <xxxxxxxxx@qq.com>
  Date:   Mon Oct 12 20:30:51 2020 +0800
  
      init

从上面可以看出来是一条直线,而如果用merge则会出现分叉。

 

三. 总结

Git其实没有那么难,但命令还是有点多,不可能都记住,最后送大家一张图来总结上面常用的命令吧,也可以设成桌面壁纸哟,撒花,完结啦

 

参考文献:

1.https://mp.weixin.qq.com/s/Km5KuXPETvG0wCGHrvj9Vg ,孟宁

 

posted @ 2020-10-12 21:40  三丁目的夕阳  阅读(216)  评论(0)    收藏  举报