Git 掌握

一、前言

大二上学期,学校开了数据库的课程,让做课程设计,数据库代码,文档等都搞好了,让老师看的时候文档写的不好,让修改,改了之后继续让老师看,来来回回弄了三四次,最后老师说:你把第一次的文档发给我吧。随着版本的不断增多,各自版本的内容是什么我们还知道吗?每个版本有各⾃的内容,但最终会只有⼀份报告需要被我们使⽤。文档是这样的,我们写的代码也是这样的。

如何解决这个问题?---- 版本控制器 Git

文件可能会有很多版本,通过版本控制器可以了解一个文件的历史,以及它发展过程中的系统。说白了,就是可以记录工程中的每一次改动和版本迭代的一个管理系统,也可以多人协同作业。

目前最主流的版本控制器是Git。Git可以控制电脑上的所有格式的文件,例如doc,execl,dwg等。当然,对于开发人员来说,Git最重要的是可以帮助我们管理软件开发项目中的源代码文件。

所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等。版本控制器可以告诉你每次的改动,比如某一行添加了什么,某一行删除了什么。但是图片,视频这些二进制文件,虽然也可以被版本控制器管理,但不能知道文件发生了什么变化,比如图片从120变成了100,图片哪里改变了,版本控制器是不知道的。

二、centos安装Git

输入git之后,如果出现git:command not found就是没有安装git。

sudo yum -y install git可以安装git。

通过git --version可以查看安装git的版本。

三、Git基本操作

(1) 创建Git本地仓库

仓库是进行版本控制的一个文件目录。我们要想对文件进行版本控制,就必须先创建一个仓库出来。

mkdir gitcode

创建仓库 git init,创建之后cd .git就可以进入到创建的本地仓库中了。.git目录是Git来跟踪管理仓库的,不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

(2) 配置Git

安装Git后首要做的事情是设置你的用户名称和e-mail地址,这是非常重要的。

配置命令为

git config user.name "name"
git config user.email "xxxxx@qq.com"

通过git config -l可以查看是否配置成功


删除配置命令

git config --unset user.name 
git config --unset user.email


git config --global user.name "name"
git config --global user.email "email"
git config -luser.name=nameuser.email=emailcore.repositoryformatversion=0core.filemode=truecore.bare=falsecore.logallrefupdates=true

这个--global是一个可选项,如果使用了这个选项,标识这台机器上所有的git仓库都会使用这个配置。如果你希望在不同仓库中使用不同的name或e-mail,可以不要--global选项,但要注意,执行命令的时候必须要在仓库里。


删除对应的配置命令为

git config [--global] --unset user.name
git config [--global] --unset user.email

(3) 认识工作区,暂存区,版本库

在仓库中创建一个ReadMe文件,Git能否管理ReadMe文件??答案是不行的。

⼯作区:是在电脑上你要写代码或⽂件的⽬录。
暂存区:英⽂叫stage或 index。⼀般存放在 .git ⽬录下的index ⽂件(.git/index)中,我们把暂存区有时也叫作索引(index)。
版本库:⼜名仓库,英⽂名repository 。⼯作区有⼀个隐藏⽬录 .git ,它不算⼯作区,是Git的版本库。这个版本库⾥⾯的所有⽂件都可以被Git管理起来,每个⽂件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原” 。

在工作区中进行新增,修改,删除等之类的操作后,修改的工作区内容会写入对象库的一个新的git对象中。将对象管理起来就可以完成对版本的管理。

所有的对象都会存在这个objects中。

四、添加文件

使用git add 文件名可以将文件添加到暂存区,也可以使用git add . 这个命令是将当前目录下面的所有文件改动到暂存区当中。

在使用git commit 命令将暂存区内容添加到本地仓库中:

提交暂存区全部内容到本地仓库中: git commit -m "message"
提交暂存区的指定⽂件到仓库区: git commit [file1] [file2] ... -m "message"

这个 "message"是要提交的细节,也可以说是这次提交版本的一个备注。


使⽤ git log 命令,来查看下历史提交记录


该命令显⽰从最近到最远的提交⽇志,并且可以看到我们commit时的⽇志消息。如果嫌输出信息太多,看得眼花缭乱的,可以试试加上 --pretty=oneline 参数:

这一大串数字是每次提交的commit id(版本号),这个数字是经过加密算法SHA1计算出来的一个非常大的数字,用十六进制表示。

五、查看.git文件

.git/
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
│?? ├── applypatch-msg.sample
│?? ├── commit-msg.sample
│?? ├── post-update.sample
│?? ├── pre-applypatch.sample
│?? ├── pre-commit.sample
│?? ├── prepare-commit-msg.sample
│?? ├── pre-push.sample
│?? ├── pre-rebase.sample
│?? └── update.sample
├── index
├── info
│?? └── exclude
├── logs
│?? ├── HEAD
│?? └── refs
│??     └── heads
│??         └── master
├── objects
│?? ├── 1e
│?? │?? └── d7c1605990be5792ee92e05286efb364b1a79f
│?? ├── 42
│?? │?? └── 8b97b82b6c59cad7488b24e6b618ebbcd819bc
│?? ├── 6f
│?? │?? └── 014900d134c7702d875fe8626fcde0ec46ce83
│?? ├── info
│?? └── pack
└── refs├── heads│?? └── master└── tags

index 就是我们的暂存区,add后的内容都是添加到这⾥的。
HEAD 就是我们的默认指向master分⽀的指针
objects为Git的对象库,⾥⾯包含了创建的各种版本库对象及内容。当执⾏git add命令时,暂存区的⽬录树被更新,同时⼯作区修改(或新增)的⽂件内容被写⼊到对象库中的⼀个新的对象中,就位于".git/objects"⽬录下.

六、修改文件

Git⽐其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,⽽⾮⽂件。

什么是修改?⽐如你新增了⼀⾏,这就是⼀个修改,删除了⼀⾏,也是⼀个修改,更改了某些字符,
也是⼀个修改,删了⼀些⼜加了⼀些,也是⼀个修改,甚⾄创建⼀个新⽂件,也算⼀个修改。让我们将 ReadMe ⽂件进⾏⼀次修改。

我对ReadMe的文件进行了修改,此时仓库中的ReadMe和我们工作区的ReadMe是不同的,如何查看当前仓库的状态呢? git status 命令用于查看你上次提交之后是否对文件进行再次修改。

上⾯的结果告诉我们,ReadMe 被修改过了,但还没有完成添加与提交 。

我们只知道文件被修改了,并不知道什么地方被修改了。


git diff [file] 命令⽤来显⽰暂存区和⼯作区⽂件的差异,显⽰的格式正是Unix通⽤的diff格式。也可以使⽤ git diff HEAD -- [file] 命令来查看版本库和⼯作区⽂件的区别。知道了对ReadMe做了什么修改后,再把它提交到本地仓库就放⼼多了 。


add之后,就没看到no changes added to commit的消息了,接下来继续commit即可。

七、版本回退

前面说过,Git能够管理文件的历史版本,这也是版本控制器的重要能力之一。如果哪天工作出现了问题,可以先回退到上一个版本重新开始,这个时候就需要版本回退的功能了。

执行git reset 命令用于回退版本,可以指定退回某一次提交的版本。当然这个回退只是将版本库中的内容进行回退,工作区或暂存区是否进行回退需要有命令参数来决定。

git reset 命令语法格式为: git reset [--soft | --mixed | --hard] [HEAD]
--mixed 为默认选项,使⽤时可以不⽤带该参数。该参数将暂存区的内容退回为指定提交版本内
容,⼯作区⽂件保持不变。
--soft 参数对于⼯作区和暂存区的内容都不变,只是将版本库回退到某个指定版本。
--hard 参数将暂存区与⼯作区都退回到指定版本。切记⼯作区有未提交的代码时不要⽤这个命令,因为⼯作区会回滚,你没有提交的代码就再也找不回了,所以使⽤该参数前⼀定要慎重

八、撤销修改

(1) 场景一 对于还没有add的代码

在代码git add之后,又新添加了几行代码,发现代码出现问题,需要回退到git add的时候,可以使用

git checkout -- filename来撤销

[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
[sxk@VM-4-13-centos gitcode]$ git checkout -- ReadMe
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
[sxk@VM-4-13-centos gitcode]$ 

(2) 场景二 已经 add ,但没有 commit

已经 add ,但没有 commit ,需要回退版本,可以使用git reset --mixed HEAD,将暂存区回退,在使用场景一中的 git checkout -- filename将工作区中的版本回退。

[sxk@VM-4-13-centos gitcode]$ git reset HEAD ReadMe
[sxk@VM-4-13-centos gitcode]$ git status
# On branch master
nothing to commit, working directory clean
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
[sxk@VM-4-13-centos gitcode]$ git checkout -- ReadMe
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!

(3) 场景三 已经 add ,并且也 commit 了

要担⼼,我们可以 git reset --hard HEAD^ 回退到上⼀个版本!不过,这是有条件的,就是你还没有把⾃⼰的本地版本库推送到远程。还记得Git是分布式版本控制系统吗?我们后⾯会讲到远程版本库,⼀旦推送到远程版本库,就真的惨了……

[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ git add ReadMe
[sxk@VM-4-13-centos gitcode]$ git commit -m "modify"
[master f5a061b] modify1 file changed, 1 insertion(+)
[sxk@VM-4-13-centos gitcode]$ git reset --hard HEAD^
HEAD is now at 1ed7c16 add first file
[sxk@VM-4-13-centos gitcode]$ git status
# On branch master
nothing to commit, working directory clean
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
[sxk@VM-4-13-centos gitcode]$ 

九、删除文件

使用rm 命令只是把文件从工作区中删除了,但是暂存区和版本库中并没有改变,可以使用git rm filename和git commit -m "message"命令,将文件从暂存区和版本库中也删除

[sxk@VM-4-13-centos gitcode]$ touch test
[sxk@VM-4-13-centos gitcode]$ git add test
[sxk@VM-4-13-centos gitcode]$ git commit -m "del test"
[master e045872] del test1 file changed, 0 insertions(+), 0 deletions(-)create mode 100644 test
[sxk@VM-4-13-centos gitcode]$ git rm test
rm 'test'
[sxk@VM-4-13-centos gitcode]$ ll
total 4
-rw-rw-r-- 1 sxk sxk 13 Mar  4 20:38 ReadMe
[sxk@VM-4-13-centos gitcode]$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	deleted:    test
#
[sxk@VM-4-13-centos gitcode]$ git commit -m "delete test"
[master 00bb8a2] delete test1 file changed, 0 insertions(+), 0 deletions(-)delete mode 100644 test
[sxk@VM-4-13-centos gitcode]$ git status
# On branch master
nothing to commit, working directory clean
[sxk@VM-4-13-centos gitcode]$ 

十、分支管理

在版本回退⾥,你已经知道,每次提交,Git都把它们串成⼀条时间线,这条时间线就可以理解为是⼀个分⽀。截⽌到⽬前,只有⼀条时间线,在Git⾥,这个分⽀叫主分⽀,即master分⽀。

再来理解⼀下HEAD,HEAD 严格来说不是指向提交,⽽是指向master,master才是指向提交的,所以,HEAD 指向的就是当前分⽀。

每次提交,master分⽀都会向前移动⼀步,这样,随着你不断提交,master分⽀的线也越来越⻓,⽽
HEAD只要⼀直指向master分⽀即可指向当前分⽀

(1) 创建分支

通过 git branch可以查看本地所有分支

[sxk@VM-4-13-centos gitcode]$ git branch
* master

通过 git branch CreateName可以创建新的分支

[sxk@VM-4-13-centos gitcode]$ git branchCreateName
* master

(2) 切换分支

如何切换到新建的分支下进行开发呢? 使用 git checkout CreateName可以完成切换

[sxk@VM-4-13-centos gitcode]$ git checkout CreateName 
Switched to branch 'CreateName'
// 在不同分支中对ReadMe进行修改。
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
------------------------------------------------------------------------------------
// 将文件提交到本地仓库
[sxk@VM-4-13-centos gitcode]$ git add ReadMe
[sxk@VM-4-13-centos gitcode]$ git commit -m "md ReadMe"
[CreateName fa00f51] md ReadMe1 file changed, 4 insertions(+)
------------------------------------------------------------------------------------
// 查看文件状态并将分支切换到master
[sxk@VM-4-13-centos gitcode]$ git status
# On branch CreateName
nothing to commit, working directory clean
[sxk@VM-4-13-centos gitcode]$ git branch
* CreateNamemaster
[sxk@VM-4-13-centos gitcode]$ git checkout master
Switched to branch 'master'
------------------------------------------------------------------------------------   
// 文件在master分支下的内容
[sxk@VM-4-13-centos gitcode]$ git branchCreateName
* master
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
------------------------------------------------------------------------------------ 
// 文件在CreateName分支下的内容
[sxk@VM-4-13-centos gitcode]$ git checkout CreateName
Switched to branch 'CreateName'
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!

为什么会出现这个现象呢?我们来看看CreateName分⽀和master分⽀指向,发现两者指向的提交是不⼀样的 。

[sxk@VM-4-13-centos gitcode]$ cat .git/refs/heads/CreateName 
fa00f518c0c2baffdd74cde515761de343dcff3d
[sxk@VM-4-13-centos gitcode]$ cat .git/refs/heads/master 
00bb8a2258f62a5afd79c77cf25549fb7a2fa6aa
[sxk@VM-4-13-centos gitcode]$ 


 

(3) 合并分支

为了在master主分⽀上能看到新的提交,就需要将 CreateName 分⽀合并到 master 分⽀ 。

将分支切换到master分支,并执行 git merge CreateName,就可以将分支合并到master中,然后在查看master中ReadMe的内容,可以发现,内容已经和CreateName分支中的ReadMe内容一样。

[sxk@VM-4-13-centos gitcode]$ git checkout master
Switched to branch 'master'
[sxk@VM-4-13-centos gitcode]$ git merge CreateName 
Updating 00bb8a2..fa00f51
Fast-forwardReadMe | 4 ++++1 file changed, 4 insertions(+)
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!

Fast-forward代表“快进模式”,也就是直接把master指向CreateName的当前提交,所以合并速度⾮常快。当然,也不是每次合并都能Fast-forward。

(4) 删除分支

合并完成后,CreateName分⽀对于我们来说就没⽤了,那么CreateName分⽀就可以被删除掉,注意如果当前正处于某分⽀下,就不能删除当前分⽀。

通过 git branch -d CreateName来删除分支

[sxk@VM-4-13-centos gitcode]$ git checkout CreateName 
Switched to branch 'CreateName'
[sxk@VM-4-13-centos gitcode]$ git branch -d CreateName 
error: Cannot delete the branch 'CreateName' which you are currently on.
[sxk@VM-4-13-centos gitcode]$ git checkout master 
Switched to branch 'master'
[sxk@VM-4-13-centos gitcode]$ git branch -d CreateName 
Deleted branch CreateName (was fa00f51).
[sxk@VM-4-13-centos gitcode]$ 

(5) 合并冲突

在实际合并当中,可能会遇到代码冲突的问题。

# 1.创建新的分支dev1,并切换到分支dev1中把ReadMe文件进行修改,然后commit到本地仓库
[sxk@VM-4-13-centos gitcode]$ git branch dev1
[sxk@VM-4-13-centos gitcode]$ git checkout dev1 
Switched to branch 'dev1'
[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
dev1 modify
[sxk@VM-4-13-centos gitcode]$ git add .
[sxk@VM-4-13-centos gitcode]$ git status
# On branch dev1
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	modified:   ReadMe
#
[sxk@VM-4-13-centos gitcode]$ git commit -m "modify ReadMe: dev1"
[dev1 b472615] modify ReadMe: dev11 file changed, 1 insertion(+)# 2. 切换到分支master中,修改ReadMe的内容,并commit到本地仓库中[sxk@VM-4-13-centos gitcode]$ git checkout master 
Switched to branch 'master'
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
master modify
[sxk@VM-4-13-centos gitcode]$ git add .
[sxk@VM-4-13-centos gitcode]$ git commit -m "modify ReadMe: master"
[master 05bf5ab] modify ReadMe: master1 file changed, 1 insertion(+)
[sxk@VM-4-13-centos gitcode]$ git branchdev1
* master# 3. 合并dev1分支到master中,发现会出现冲突问题,并且ReadMe文件中的内容也会出现一些其他内容[sxk@VM-4-13-centos gitcode]$ git merge dev1
Auto-merging ReadMe
CONFLICT (content): Merge conflict in ReadMe
Automatic merge failed; fix conflicts and then commit the result.
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
<<<<<<< HEAD
master modify
=======
dev1 modify
>>>>>>> dev1
[sxk@VM-4-13-centos gitcode]$ 

此时我们必须要⼿动调整冲突代码,并需要再次提交修正后的结果!!(再次提交很重要,切勿忘
记)

[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
master modify
[sxk@VM-4-13-centos gitcode]$ git add .
[sxk@VM-4-13-centos gitcode]$ git commit -m "merge master"
[master 17985b9] merge master
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
master modify
[sxk@VM-4-13-centos gitcode]$ 

最后,不要忘记dev1分⽀使⽤完毕后就可以删除了

十一、分支管理策略

在这种 Fast forward 模式下,删除分⽀后,查看分⽀历史时,会丢掉分⽀信息,看不出来最新提交到底是merge进来的还是正常提交的 。

Git ⽀持我们强制禁⽤ Fast forward 模式,那么就会在 merge 时⽣成⼀个新的 commit ,这样,从分⽀历史上就可以看出分⽀信息。下⾯我们实战⼀下 --no-ff ⽅式的 git merge 。⾸先,创建新的分⽀ dev2 ,并切换⾄新的分⽀。所以在合并分⽀时,加上 --no-ff 参数就可以⽤普通模式合并,合并后的历史有分⽀,能看出来曾经做过合并,⽽ fast forward 合并就看不出来曾经做过合并。
创建一个新的分支,然后修改ReadMe中的内容,add,commit之后,切换分支到master,合并分支的时候使用

git merge --no-ff -m "merge dev" dev命令 -m ""是用来记录信息的。

[sxk@VM-4-13-centos gitcode]$ git merge --no-ff -m "merge dev" dev
Already up-to-date.
[sxk@VM-4-13-centos gitcode]$ cat ReadMe 
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
HELLO WORLD!
master modify
我是dev
[sxk@VM-4-13-centos gitcode]$ git log --graph --abbrev-commit 
*   commit cd08c07
|\  Merge: 17985b9 16286a2
| | Author: user <email>
| | Date:   Tue Mar 5 19:29:50 2024 +0800
| | 
| |     A
| |     A
| |     Merge branch 'dev'

(1) master分支

在实际开发中,master分支应该是非常稳定的,也就是仅仅用来发布新版本,平时不能在上面干活,干活都是在dev分支上,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的同学在做项目的时候,每个人都有自己的分支,时不时的往dev分支上合并就可以了。

(2) bug分支

假如我们现在正在dev2分⽀上进⾏开发,开发到⼀半,突然发现 master 分⽀上⾯有bug,需要解决。在Git中,每个bug都可以通过⼀个新的临时分⽀来修复,修复后,合并分⽀,然后将临时分⽀
删除。可现在dev2的代码在⼯作区中开发了⼀半,还⽆法提交,怎么办?

git 提供了 git stash命令,可以将当前工作区信息进行存藏,被存藏的内容可以恢复出来。

[sxk@VM-4-13-centos gitcode]$ git checkout -b dev3
Switched to a new branch 'dev3'
[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ git stash
Saved working directory and index state WIP on dev3: cd08c07 A A Merge branch 'dev'
HEAD is now at cd08c07 A

现在就可以区修bug了

[sxk@VM-4-13-centos gitcode]$ git checkout -b fix_bug
Switched to a new branch 'fix_bug'
[sxk@VM-4-13-centos gitcode]$ git checkout master 
Switched to branch 'master'
[sxk@VM-4-13-centos gitcode]$ git merge -m "" fix_bug 
Already up-to-date.
[sxk@VM-4-13-centos gitcode]$ git branch -d fix_bug 
Deleted branch fix_bug (was cd08c07).

在bug修复完成之后,切换到master分支,完成合并,将bug分支删除。

切回dev3分支,通过 git stash list可以看到刚才存藏的工作现场。

[sxk@VM-4-13-centos gitcode]$ git stash list
stash@{0}: WIP on dev3: cd08c07 A A Merge branch 'dev'

使用 git stash pop命令可以在恢复工作区的同时把stash给删除了。

[sxk@VM-4-13-centos gitcode]$ git checkout dev3 
Switched to branch 'dev3'
[sxk@VM-4-13-centos gitcode]$ git stash list
stash@{0}: WIP on dev3: cd08c07 A A Merge branch 'dev'
[sxk@VM-4-13-centos gitcode]$ git stash pop
# On branch dev3
# 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:   ReadMe
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (a13b34d28bdb8d5374b115c2f1dc817ac040fc9b)
[sxk@VM-4-13-centos gitcode]$ 再次查看的时候,就没有现场可以恢复了。
[sxk@VM-4-13-centos gitcode]$ git stash list
[sxk@VM-4-13-centos gitcode]$ 

另外,恢复现场也可以采⽤ git stash apply 恢复,但是恢复后,stash内容并不删除,你需要⽤ git stash drop 来删除;你可以多次stash,恢复的时候,先⽤ git stash list 查看,然后恢复指定的stash,⽤命令git stash apply stash@{0}


注意一个细节,我们让dev3进行的存藏,然后去修复master的bug,在解决bug之后,将bug分支和master分支进行了合并,但是,dev3中的master内容并不是解决完bug之后的master内容,在dev3中是看不到修复bug的相关代码的。

我们的最终⽬的是要让 master 合并 dev2 分⽀的,那么正常情况下我们切回 master 分⽀直接合并即可,但这样其实是有⼀定⻛险的。是因为在合并分⽀时可能会有冲突,⽽代码冲突需要我们⼿动解决(在 master 上解决)。我们⽆法保证对于冲突问题可以正确地⼀次性解决掉,因为在实际的项⽬中,代码冲突不只⼀两⾏那么简单,有可能⼏⼗上百⾏,甚⾄更多,解决的过程中难免⼿误出错,导致错误的代码被合并到 master 上。此时的状态为:

解决这个问题的⼀个好的建议就是:最好在⾃⼰的分⽀上合并下 master ,再让 master 去合并dev ,这样做的⽬的是有冲突可以在本地分⽀解决并进⾏测试,⽽不影响 master 。此时的状态为
 

(3) 删除临时分支

在开发的过程中,会有新功能要添加进来。添加一个新功能的时候,会先新建一个分支,在这个分支上面开发,完成后在合并,最后删除这个分支。

如果这个在这个分支上开发了一半,突然就不需要继续开发了,这个分支就要销毁了,留着没啥用了。这个时候,传统的 git branch -d命令删除分支的方法是不行的。

把小d换成D就可以强制删除了。

[sxk@VM-4-13-centos gitcode]$ git checkout -b dev4
M	ReadMe
Switched to a new branch 'dev4'
[sxk@VM-4-13-centos gitcode]$ vim ReadMe 
[sxk@VM-4-13-centos gitcode]$ git add .
[sxk@VM-4-13-centos gitcode]$ git commit -m "dev4"
[dev4 d7b27ca] dev41 file changed, 2 insertions(+)
[sxk@VM-4-13-centos gitcode]$ git checkout master 
Switched to branch 'master'
[sxk@VM-4-13-centos gitcode]$ git branch -d dev4
error: The branch 'dev4' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dev4'.
[sxk@VM-4-13-centos gitcode]$ git branch -D dev4
Deleted branch dev4 (was d7b27ca).

十二、远程操作

前面所说的所有内容,都是在本地,也就是我们自己的计算机上,但是我们的git其实是分布式版本控制系统。同一个git仓库,可以分部到不同的机器上。我们可以将Git仓库托管到github或者gitee上,就可以免费获得git远程仓库。github是国外的网站,速度可能会比较慢。

(1) 新建远程仓库

点 New repository可以创建仓库。

这里我选的是public

这样就可以简单的创建一个远程仓库了。


如果你写了一个项目并且公开了,那么别人在阅读你的代码的时候发现问题了,这个时候别人就可以在lssues中提出问题。


在实际的开发中,并不会直接让代码和master分支进行合并,而是会PR(Pull Requests)拉去一个请求,来帮助自己和别人协作编写代码,然后由管理员同意了,才可以进行merge。

(2) 克隆远程仓库

a. 通过HTTPS克隆

克隆/下载远端仓库到本地,需要使⽤ git clone 命令,后⾯跟上我们的远端仓库的链接

[sxk@VM-4-13-centos storage]$ git clone https://github.com/HaiFanNeon/remote-github.git
Cloning into 'remote-github'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
[sxk@VM-4-13-centos storage]$ ls
gitcode  remote-github
[sxk@VM-4-13-centos storage]$ 

如果你是第一次clone的话,需要输入你github或者gitee的用户和密码。

[sxk@VM-4-13-centos remote-github]$ ls -al
total 16
drwxrwxr-x 3 sxk sxk 4096 Mar  6 18:52 .
drwxrwxr-x 4 sxk sxk 4096 Mar  6 18:51 ..
drwxrwxr-x 8 sxk sxk 4096 Mar  6 18:52 .git
-rw-rw-r-- 1 sxk sxk   30 Mar  6 18:52 README.md

这个仓库里面有创建远程仓库时候选择的 add a README file选项自动创建的README文件。

b. 通过SSH克隆

SSH协议是采用的公钥加密和解密的过程,所以我们需要先添加一个public key,将本地服务器上的public key添加到github中。

[sxk@VM-4-13-centos storage]$ git clone git@github.com:HaiFanNeon/remote-github.git
Cloning into 'remote-github'...
The authenticity of host 'github.com' can't be established.
Are you sure you want to continue connecting (yes/no)? y
Please type 'yes' or 'no': yes
Warning: Permanently added 'github.com' (ECDSA) to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.Please make sure you have the correct access rights
and the repository exists.
[sxk@VM-4-13-centos storage]$ 

在没有配置public key的情况下强行clone就会出现报错。


第⼀步:创建SSH Key。在⽤⼾主⽬录下,看看有没有.ssh⽬录,如果有,再看看这个⽬录下有没有
id_rsa 和 id_rsa.pub 这两个⽂件,如果已经有了,可直接跳到下⼀步。如果没有,需要创建
SSH Key:

[sxk@VM-4-13-centos .ssh]$ ssh-keygen -t rsa -C "email" // 这里的邮箱要跟你的github或者gitee中的邮箱相对应
Generating public/private rsa key pair.
Enter file in which to save the key (/home/sxk/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/sxk/.ssh/id_rsa.
Your public key has been saved in /home/sxk/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:+6hLrOOna4IrASg/tkF8Jd4jlfpUIDU7awZMxCbla3M haifan0312@163.com
The key's randomart image is:
+---[RSA 2048]----+    |
+----[SHA256]-----+把id_rsa.pub中的密钥拷贝到github或者gitee中

[sxk@VM-4-13-centos storage]$ git clone git@github.com:HaiFanNeon/remote-github.git
Cloning into 'remote-github'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
[sxk@VM-4-13-centos storage]$ 

当我们在使用ssh进行clone的时候就可以完成了。


如果有多个⼈协作开发,GitHub/Gitee允许添加多个公钥,只要把每个⼈的电脑上的Key都添加到GitHub/Gitee,就可以在每台电脑上往GitHub/Gitee上提交推送了 。

(3) 向远程仓库推送

本地已经 clone 成功远程仓库后,我们便可以向仓库中提交内容(git push命令)

git push <远程主机名> <本地分⽀名>:<远程分⽀名>
如果本地分⽀名与远程分⽀名相同,则可以省略冒号:
git push <远程主机名> <本地分⽀名>

sxk@VM-4-13-centos storage]$ 先进入到remote目录下面^C
[sxk@VM-4-13-centos storage]$ cd remote-github/
[sxk@VM-4-13-centos remote-github]$ ls
README.md
[sxk@VM-4-13-centos remote-github]$ touch hello_world.cc
[sxk@VM-4-13-centos remote-github]$ vim hello_world.cc 
[sxk@VM-4-13-centos remote-github]$ 写了一个helloworld的代码^C
[sxk@VM-4-13-centos remote-github]$ 现在将这个代码推送到远程仓库^C
[sxk@VM-4-13-centos remote-github]$ git config -l
user.name=name
user.email=email
name和email要和github/gitee中的name和email对应
[sxk@VM-4-13-centos remote-github]$  git add .
[sxk@VM-4-13-centos remote-github]$ git commit -m "create hello_world.cc"
[main 3914558] create hello_world.cc1 file changed, 7 insertions(+)create mode 100644 hello_world.cc
[sxk@VM-4-13-centos remote-github]$ git push origin(是往远程推送的) main(推送的是本地的main分支):main(推送到远程分支main中,如果远程分支和本地分支一样,可以省略远程分支 不写)^C
[sxk@VM-4-13-centos remote-github]$ git push origin main 
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 372 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: To git@github.com:HaiFanNeon/remote-github.git9bdd187..3914558  main -> main
[sxk@VM-4-13-centos remote-github]$ 

这就推送成功了。

(4) 拉取远程仓库

我在github上对代码进行了修改,但是本地仓库中的这个代码还是以前的。远程仓库领先本地仓库一个版本,为了使本地仓库处于最新的版本,需要拉去远端代码,并合并到本地。git 提供了 git pull命令,该命令用于从远程获取代码并合并本地的版本。

git pull <远程主机名> <远程分⽀名>:<本地分⽀名>
如果远程分⽀是与当前分⽀合并,则冒号后⾯的部分可以省略。
git pull <远程主机名> <远程分⽀名>

[sxk@VM-4-13-centos remote-github]$ git pull origin main
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:HaiFanNeon/remote-github* branch            main       -> FETCH_HEAD
Updating 3914558..a192e7e
Fast-forwardhello_world.cc | 6 +++++-1 file changed, 5 insertions(+), 1 deletion(-)
[sxk@VM-4-13-centos remote-github]$ cat hello_world.cc 
#include <iostream>int main()
{for (int i = 0; i < 10; i++){std::cout << "hello github" << std::endl;}return 0;
}
[sxk@VM-4-13-centos remote-github]$ 

拉取成功。

十三、配置git

(1) .gitignore忽略特殊文件

在我们创建仓库的时候,有一个添加.gitignore(.git ignore)选项,

当工作目录下面文件非常多的时候,要add,一般会使用add .,但是因为文件非常多,不想要的文件也会add,如何让git只添加我们需要的文件?

在Git⼯作区的根⽬录下创建⼀个特殊的 .gitignore ⽂件,然后把要忽略的⽂件名填进去,Git就会⾃动忽略这些⽂件了 。

如果当时没有选择这个选择,在⼯作区创建⼀个也是可以的。⽆论哪种⽅式,最终都可以得到⼀个完
整的 .gitignore ⽂件,例如我们想忽略以 .py 结尾所有⽂件,
.gitignore 的内容如下

[sxk@VM-4-13-centos remote-github]$ touch .gitignore
[sxk@VM-4-13-centos remote-github]$ vim .gitignore 
[sxk@VM-4-13-centos remote-github]$ cat .gitignore 
*.so
[sxk@VM-4-13-centos remote-github]$ git add .
[sxk@VM-4-13-centos remote-github]$ git status
# On branch main
# Your branch is ahead of 'origin/main' by 1 commit.
#   (use "git push" to publish your local commits)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#	new file:   .gitignore
#
[sxk@VM-4-13-centos remote-github]$ 

可以看到,我新增了两个文件,一个.gitignore一个a.so文件,但是add之后,查看文件状态,会显示只有.gitignore是新增文件。我们commit和push一下,到远端查看。


只有gitignore文件推送到了远端。


把指定⽂件排除在外的写法就是 ! +⽂件名,所以,只需把例外⽂件添加进去即可。

例如
.* // 排除所有.开头的隐藏文件
!.gitignore // 不排除.gitignore文件

(2) 给命令配置别名

在我们使⽤Git期间,有些命令敲的时候着实让⼈头疼(太⻓了。。),幸运的是,git⽀持对命令进⾏简化!
举个例⼦,将 git status 简化为 git st ,对应的命令为:

git config --global alias.st status

--global 参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都有⽤。如果不加,那只
针对当前的仓库起作⽤ 。

十四、标签管理

(1) 理解标签

标签 tag ,可以简单的理解为是对某次 commit 的⼀个标识,相当于起了⼀个别名。例如,在项⽬发布某个版本的时候,针对最后⼀次 commit 起⼀个 v1.0 这样的标签来标识。
这有什么⽤呢?相较于难以记住的 commit id , tag 很好的解决这个问题,因为 tag ⼀定要给⼀
个让⼈容易记住,且有意义的名字。当我们需要回退到某个重要版本时,直接使⽤标签就能很快定位
到。

(2) 创建标签

  1. 切换到需要打标签的分支上
  2. git tag [name] 可以打一个新标签
    [sxk@VM-4-13-centos remote-github]$ git tag v1.0
  3. git tag查看所有标签

默认标签是打在最新提交的 commit 上的。那如何在指定的commit上打标签呢?⽅法是找到历史提
交的commit id,然后打上就可以了,⽰例如下

[sxk@VM-4-13-centos remote-github]$ git log --pretty=oneline 
c00bceacd1760b6663b28876670757297b41c302 要忽略的文件
a192e7e29a531e6f5bbd43a6d8bd9f55c8289602 Update hello_world.cc
3914558f6f6884059ad67fff5aefa46062880701 create hello_world.cc
9bdd187d73e77502f164372852d1f54b07b7f775 Initial commit
[sxk@VM-4-13-centos remote-github]$ git log --pretty=oneline --abbrev-commit 
c00bcea 要忽略的文件
a192e7e Update hello_world.cc
3914558 create hello_world.cc
9bdd187 Initial commit
[sxk@VM-4-13-centos remote-github]$ git tag v9.99 a192e7e
[sxk@VM-4-13-centos remote-github]$ git tag
v1.0
v9.99

注意,标签不是按时间顺序列出,⽽是按字⺟排序的。可以⽤ git show [tagname] 查看标签信息。

[sxk@VM-4-13-centos remote-github]$ git show v1.0
commit c00bceacd1760b6663b28876670757297b41c302
Author: HaiFanNeon <haifan0312@163.com>
Date:   Wed Mar 6 19:43:28 2024 +0800要忽略的文件diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..140f8cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.so

Git还提供可以创建带有说明的标签,⽤-a指定标签名,-m指定说明⽂字,格式为

git tag -a [name] -m "XXX" [commit_id]

[sxk@VM-4-13-centos remote-github]$ git show v99.9
tag v99.9
Date:   Wed Mar 6 20:00:54 2024 +0800important tag:XXXcommit c00bceacd1760b6663b28876670757297b41c302
Date:   Wed Mar 6 19:43:28 2024 +0800要忽略的文件diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..140f8cf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.so

(3) 操作标签

如果标签打错了,也可以删除 。使用git tag -d tagname

[sxk@VM-4-13-centos remote-github]$ git tag -d v1.0
Deleted tag 'v1.0' (was c00bcea)
[sxk@VM-4-13-centos remote-github]$ git show v1.0
fatal: ambiguous argument 'v1.0': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
[sxk@VM-4-13-centos remote-github]$ 

因为创建的标签都只存储在本地,不会⾃动推送到远程。所以,打错的标签可以在本地安全删除。
如果要推送某个标签到远程,使⽤命令 git push origin <tagname>

[sxk@VM-4-13-centos remote-github]$ git push origin v99.9
Counting objects: 1, done.
Writing objects: 100% (1/1), 169 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
remote: To git@github.com:HaiFanNeon/remote-github.git* [new tag]         v99.9 -> v99.9
[sxk@VM-4-13-centos remote-github]$ 


将所有标签推送到远端 git push origin --tags

[sxk@VM-4-13-centos remote-github]$ git push origin --tags 
Counting objects: 1, done.
Writing objects: 100% (1/1), 168 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
remote: To git@github.com:HaiFanNeon/remote-github.git* [new tag]         v9.9 -> v9.9* [new tag]         v9.99 -> v9.99
[sxk@VM-4-13-centos remote-github]$ 


如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除。

[sxk@VM-4-13-centos remote-github]$ git tag -d v9.9
Deleted tag 'v9.9' (was d441e7e)
[sxk@VM-4-13-centos remote-github]$ git push origin :v9.9
remote: To git@github.com:HaiFanNeon/remote-github.git- [deleted]         v9.9
[sxk@VM-4-13-centos remote-github]$ 



 

十五、多人协作

(1) 多人协作

目标:远程main分支下的helloworld.cc文件新增代码"aaa"、“bbb”;

实现:由开发者1新增“aaa”, 由开发者2新增“bbb”

条件:在一个分支下协作完成

在github中新建了一个dev分支,将dev分支拉取到本地仓库中

[sxk@VM-4-13-centos remote-github]$ git pull
From github.com:HaiFanNeon/remote-github* [new branch]      dev        -> origin/dev
Already up-to-date.
[sxk@VM-4-13-centos remote-github]$ git branch
* main
[sxk@VM-4-13-centos remote-github]$ git branch -rorigin/HEAD -> origin/mainorigin/devorigin/main

用户1已经完成对helloworld文件的修改

[sxk@VM-4-13-centos remote-github]$ vim hello_world.cc 
[sxk@VM-4-13-centos remote-github]$ cat hello_world.cc 
#include <iostream>int main()
{for (int i = 0; i < 10; i++){std::cout << "hello github" << std::endl;}std::cout << "aaa" << std::endl; return 0;
}
[sxk@VM-4-13-centos remote-github]$ 

通过add,commit,push将代码提交到远端。


此时用户2对helloworld文件进行修改。修改之后add,commit,push

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.

会出现错误,因为用户1修改之后内容已经改变,用户2需要先将远端拉取到本地,解决冲突,然后在push。


其实在实际开发中,遇到了这种冲突的问题是非常烦的,在解决冲突的时候,可能会把好的代码给删了,从而出现问题,所以在协作开发的时候,一般不会在同一个分支中开发。

在不同分支下协作完成,各自让某一个功能私有一个分支。

在本地创建的分⽀也可以通过推送的⽅式发送到远端 。

[sxk@VM-4-13-centos remote-github]$ git checkout -b featuer-1
Switched to a new branch 'featuer-1'
[sxk@VM-4-13-centos remote-github]$ vim fucntion1
[sxk@VM-4-13-centos remote-github]$ cat fucntion1 
aaaaaa
[sxk@VM-4-13-centos remote-github]$ git add fucntion1
[sxk@VM-4-13-centos remote-github]$ git commit -m "add fucntion1"
[featuer-1 29ce283] add fucntion11 file changed, 1 insertion(+)create mode 100644 fucntion1
[sxk@VM-4-13-centos remote-github]$ git push origin featuer-1 
Counting objects: 4, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 267 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote: 
remote: Create a pull request for 'featuer-1' on GitHub by visiting:
remote:      https://github.com/HaiFanNeon/remote-github/pull/new/featuer-1
remote: 
remote: To git@github.com:HaiFanNeon/remote-github.git* [new branch]      featuer-1 -> featuer-1
[sxk@VM-4-13-centos remote-github]$ 


我在我的windows里面下载了个git,然后用windows端来模拟合作人员,合作人员创建了feature-2分支并提交到远端。

Lenovo@DESKTOP-5A1B7J0 MINGW64 ~/Desktop/杂件/remote-github (main)
$ git checkout -b feature-2
Switched to a new branch 'feature-2'Lenovo@DESKTOP-5A1B7J0 MINGW64 ~/Desktop/杂件/remote-github (feature-2)
$ vim feature2Lenovo@DESKTOP-5A1B7J0 MINGW64 ~/Desktop/杂件/remote-github (feature-2)
$ cat feature2
bbbbbbLenovo@DESKTOP-5A1B7J0 MINGW64 ~/Desktop/杂件/remote-github (feature-2)
$ git add .
warning: LF will be replaced by CRLF in feature2.
The file will have its original line endings in your working directoryLenovo@DESKTOP-5A1B7J0 MINGW64 ~/Desktop/杂件/remote-github (feature-2)
$ git commit -m "add feature2"
[feature-2 0579275] add feature21 file changed, 1 insertion(+)create mode 100644 feature2Lenovo@DESKTOP-5A1B7J0 MINGW64 ~/Desktop/杂件/remote-github (feature-2)
$ git push origin feature-2
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 16 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 853 bytes | 853.00 KiB/s, done.
Total 9 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 2 local objects.
remote:
remote: Create a pull request for 'feature-2' on GitHub by visiting:
remote:      https://github.com/HaiFanNeon/remote-github/pull/new/feature-2
remote:
To https://github.com/HaiFanNeon/remote-github.git* [new branch]      feature-2 -> feature-2

在本地,你看不⻅他新建的⽂档,他看不⻅你新建的⽂档。并且推送各⾃的分⽀时,并没有任何冲突,你俩互不影响,⽤起来很舒服!


正常情况下,你俩就可以在⾃⼰的分⽀上进⾏专业的开发了!但天有不测⻛云,你的⼩伙伴突然⽣病了,但需求还没开发完,需要你帮他继续开发,于是他便把feature-2分⽀名告诉你了。这时你就需要在⾃⼰的机器上切换到feature-2分⽀帮忙继续开发,要做的操作如下

[sxk@VM-4-13-centos remote-github]$ git pull // 拉取
remote: Enumerating objects: 13, done.
remote: Counting objects: 100% (13/13), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 9 (delta 4), reused 9 (delta 4), pack-reused 0
Unpacking objects: 100% (9/9), done.
From github.com:HaiFanNeon/remote-github* [new branch]      feature-2  -> origin/feature-2
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
See git-pull(1) for detailsgit pull <remote> <branch>If you wish to set tracking information for this branch you can do so with:git branch --set-upstream-to=origin/<branch> featuer-1[sxk@VM-4-13-centos remote-github]$ git branch 
* featuer-1main
[sxk@VM-4-13-centos remote-github]$ git branch -a
* featuer-1mainremotes/origin/HEAD -> origin/mainremotes/origin/devremotes/origin/featuer-1remotes/origin/feature-2remotes/origin/main
// 切换成功后,便可以看⻅feature-2分⽀中的function2⽂件了,接着就可以帮⼩伙伴进⾏开发。
[sxk@VM-4-13-centos remote-github]$ git checkout -b feature-2 origin/feature-2
Branch feature-2 set up to track remote branch feature-2 from origin.
Switched to a new branch 'feature-2'
[sxk@VM-4-13-centos remote-github]$ 

(2) 将内容合并到master

在远端合并分支的话很简单,github中有提示,跟着提示点点点就完事了。在以后合并分支的时候,审查员可能不会是自己。

合并完之后,就可以把feature12分支给删除了。


(3) 远程分⽀删除后,本地git branch -a依然能看到的解决办法

当前我们已经删除了远程的⼏个分⽀,使⽤ git branch -a 命令可以查看所有本地分⽀和远程分
⽀,但发现很多在远程仓库已经删除的分⽀在本地依然可以看到。

[sxk@VM-4-13-centos remote-github]$ git branch -afeatuer-1
* feature-2mainremotes/origin/HEAD -> origin/mainremotes/origin/devremotes/origin/featuer-1remotes/origin/feature-2remotes/origin/main
[sxk@VM-4-13-centos remote-github]$ 

使⽤命令 git remote show origin ,可以查看remote地址,远程分⽀,还有本地分⽀与之相对应关系等信息。

[sxk@VM-4-13-centos remote-github]$ git remote show origin 
* remote originFetch URL: git@github.com:HaiFanNeon/remote-github.gitPush  URL: git@github.com:HaiFanNeon/remote-github.gitHEAD branch: mainRemote branches:main                          trackedrefs/remotes/origin/dev       stale (use 'git remote prune' to remove)refs/remotes/origin/featuer-1 stale (use 'git remote prune' to remove)refs/remotes/origin/feature-2 stale (use 'git remote prune' to remove)Local branches configured for 'git pull':feature-2 merges with remote feature-2main      merges with remote mainLocal ref configured for 'git push':main pushes to main (local out of date)

此时我们可以看到那些远程仓库已经不存在的分⽀,根据提⽰,使⽤git remote prune
origin
命令

[sxk@VM-4-13-centos remote-github]$ git remote prune origin 
Pruning origin
URL: git@github.com:HaiFanNeon/remote-github.git* [pruned] origin/dev* [pruned] origin/featuer-1* [pruned] origin/feature-2
[sxk@VM-4-13-centos remote-github]$ 

删除完毕

这样就删除了那些远程仓库不存在的分⽀。对于本地仓库的删除,前面说过。git branch -d

十六、企业级开发模型

⼀个软件从零开始到最终交付,⼤概包括以下⼏个阶段:规划、编码、构建、测试、发布、部署和维护 。

最初,程序⽐较简单,⼯作量不⼤,程序员⼀个⼈可以完成所有阶段的⼯作。但随着软件产业的⽇益
发展壮⼤,软件的规模也在逐渐变得庞⼤。软件的复杂度不断攀升,⼀个⼈已经hold不住了,就开始
出现了精细化分⼯。如下图所⽰
 


但在传统的IT组织下,开发团队(Dev)和运维团队(Ops)之间诉求不同:
• 开发团队(尤其是敏捷团队)追求变化
• 运维团队追求稳定
双⽅往往存在利益的冲突。⽐如,精益和敏捷的团队把持续交付作为⽬标,⽽运维团队则为了线上的
稳定⽽强调变更控制。部⻔墙由此建⽴起来,这当然不利于 IT 价值的最⼤化。
为了弥合开发和运维之间的鸿沟,需要在⽂化、⼯具和实践⽅⾯的系列变⾰⸺DevOps正式登上舞
台。
DevOps(Development和Operations的组合词)是⼀种重视“软件开发⼈员(Dev)”和“IT运维技术⼈员(Ops)”之间沟通合作的⽂化、运动或惯例。透过⾃动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。在DevOps的软件开发过程包含计划、编码、构建、测试、预发布、发布、运维、监控,由此可⻅DevOps的强⼤。举⼀个很简单的例⼦就能说明这个问题。⼀个软件的迭代,在我们开发⼈员看来,说⽩了就是对代码进⾏迭代,那么就需要对代码进⾏管理。如何管理我们的代码呢,那不就是Git(分布式版本控制系统)!所以Git对于我们开发⼈员来说其重要性就不⾔⽽喻了
 

(1) 系统开发环境

用户访问的网站,软件等,都是部署到服务器上稳定的代码,开发人员拥有自己的服务器,服务器中部署的是开发中的代码。

用户和开发人员之间被不同的环境隔离开,用户访问的是线上/发布环境, 开发人员访问的是开发环境。

  1. 开发环境:开发环境是程序猿们专⻔⽤于⽇常开发的服务器。为了开发调试⽅便,⼀般打开全部错
    误报告和测试⼯具,是最基础的环境。
  2. 测试环境:⼀个程序在测试环境⼯作不正常,那么肯定不能把它发布到⽣产机上。该环境是开发环
    境到⽣产环境的过渡环境。
  3. 预发布环境:该环境是为避免因测试环境和线上环境的差异等带来的缺陷漏测⽽设⽴的⼀套环境。
    其配置等基本和⽣产环境⼀致,⽬的是能让我们发正式环境时更有把握!所以预发布环境是你的产
    品质量最后⼀道防线,因为下⼀步你的项⽬就要上线了。要注意预发布环境服务器不在线上集成服
    务器范围之内,为单独的⼀些机器。
  4. ⽣产环境:是指正式提供对外服务的线上环境,例如我们⽬前在移动端或PC端能访问到的APP都是
    ⽣产环境。


这⼏个环境也可以说是系统开发的三个重要阶段:开发->测试->上线。⼀张图总结:


对于规模稍微⼤点的公司来说,可不⽌这么⼏个环境,⽐如项⽬正式上线前还存在仿真/灰度环境,再⽐如还存在多套测试环境,以满⾜不同版本上线前测试的需要。⼀个项⽬的开始从设计开始,⽽⼀个项⽬的成功则从测试开始。⼀套良好的测试体系可以将系统中绝⼤部分的致命Bug解决在系统上线之前。测试系统的完善和成熟也是衡量⼀个软件企业整体⽔平的重要指标之⼀,测试往往被忽视,因为它对可以的隐性、对软件开发企业不产⽣直接的效益,但是它却是软件质量的最终保障,乃⾄项⽬能否成功的重要因素 。

 

(2) Git分支设计规范

环境有了概念后,那么对于开发⼈员来说,⼀般会针对不同的环境来设计分⽀,

分支

名称

使用环境

master

主分支

生产环境

release

预发布分支

预发布/测试环境

develop

开发分支

开发环境

feature

需求开发分支

本地

hotfix

紧急修复分支

本地

master 分⽀
• master 为主分⽀,该分⽀为只读且唯⼀分⽀。⽤于部署到正式发布环境,⼀般由合并
release 分⽀得到。
• 主分⽀作为稳定的唯⼀代码库,任何情况下不允许直接在 master 分⽀上修改代码。
• 产品的功能全部实现后,最终在master分⽀对外发布,另外所有在master分⽀的推送应该打标签
(tag)做记录,⽅便追溯。
• master 分⽀不可删除。
release 分⽀
• release 为预发布分⽀,基于本次上线所有的 feature 分⽀合并到 develop 分⽀之后,基
于 develop 分⽀创建。可以部署到测试或预发布集群。
• 命名以 release/ 开头,建议的命名规则: release/version_publishtime 。
• release 分⽀主要⽤于提交给测试⼈员进⾏功能测试。发布提测阶段,会以 release 分⽀代码
为基准进⾏提测。
• 如果在 release 分⽀测试出问题,需要回归验证 develop 分⽀看否存在此问题。
• release 分⽀属于临时分⽀,产品上线后可选删除。
develop 分⽀
• develop 为开发分⽀,基于master分⽀创建的只读且唯⼀分⽀,始终保持最新完成以及 bug 修
复后的代码。可部署到开发环境对应集群。
• 可根据需求⼤⼩程度确定是由 feature 分⽀合并,还是直接在上⾯开发(⾮常不建议)。
feature 分⽀
• feature 分⽀通常为新功能或新特性开发分⽀,以 develop 分⽀为基础创建 feature 分
⽀。
• 命名以 feature/ 开头,建议的命名规则: feature/user_createtime_feature 。
• 新特性或新功能开发完成后,开发⼈员需合到 develop 分⽀。
• ⼀旦该需求发布上线,便将其删除。
hotfix分⽀
• hotfix 分⽀为线上 bug 修复分⽀或叫补丁分⽀,主要⽤于对线上的版本进⾏ bug 修复。当线上
出现紧急问题需要⻢上修复时,需要基于 master 分⽀创建 hotfix 分⽀。
• 命名以 hotfix/ 开头,建议的命名规则: hotfix/user_createtime_hotfix
• 当问题修复完成后,需要合并到 master 分⽀和 develop 分⽀并推送远程。⼀旦修复上线,便
将其删除。

以上说的是企业级常⽤的⼀种Git分⽀设计规范:Git Flow模型

十七、结尾

关于Git的内容就到此结束。希望对大家有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/518802.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode每日一题之 快乐数

目录 题目介绍&#xff1a; 算法原理&#xff1a; 鸽巢原理&#xff1a; 如何找到环里元素&#xff1a; 代码实现&#xff1a; 题目介绍&#xff1a; 题目链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 算法原理&#xff1a; 我先简单举两个例子&#xff…

wsl 安装 ubuntu

文章目录 打开Windows PowerShell查看可安装的ubuntu安装相对应的ubuntu将用户添加到sudoers文件中&#xff0c;并赋予了该用户sudo权限。 打开Windows PowerShell 以管理员的身份运行 查看可安装的ubuntu wsl.exe --list --online安装相对应的ubuntu wsl --install 版本…

redis-集群 原生部署和工具自动部署

什么redis集群&#xff1f; redis集群是一个提供在多个redis节点之间共享数据的程序集。它并不像redis主从复制模式那样仅提供一个master节点来提供写服务&#xff0c;而是会提供多个master节点来提供写服务&#xff0c;每个master节点中存储的数据都不一样&#xff0c;这些数据…

★【二叉搜索树插入新的节点】【二叉搜索树】Leetcode 701. 二叉搜索树中的插入操作

【二叉搜索树插入新的节点】【二叉搜索树】Leetcode 701. 二叉搜索树中的插入操作 关键点&#xff1a;解法 递归法解法 迭代法 ---------------&#x1f388;&#x1f388;题目链接&#x1f388;&#x1f388;------------------- 关键点&#xff1a; 关键点&#xff1a; 二叉…

Java项目:41 springboot大学生入学审核系统的设计与实现010

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本大学生入学审核系统管理员和学生。 管理员功能有个人中心&#xff0c;学生管理&#xff0c;学籍信息管理&#xff0c;入学办理管理等。 学生功能有…

线上问题:新需求放量后频繁发生old gc

线上问题&#xff1a;新需求放量后频繁发生old gc 一、线上问题描述二、处理问题过程1、考虑机器扩容1.1 预发环境复现该问题1.2 预发环境机器扩容1.3 预发环境验证 2、堆内存分析2.1 内存分析2.2 问题修复 三、复盘 一、线上问题描述 周四上线了一个新需求&#xff0c;该需求…

教程篇:Groq API+沉浸式翻译插件 体验最快AI翻译

1、进入https://console.groq.com/keys 申请一个API&#xff08;目前免费&#xff01;抓紧白嫖&#xff09; 2、安装Chrome插件&#xff1a;沉浸式翻译。 https://immersivetranslate.com/ 3、照着抄&#xff08;注意将apikey&#xff0c;换成自己申请的groq的api-key&…

【linuxC语言】系统调用IO文件操作

文章目录 前言一、文件描述符介绍二、系统调用IO API介绍2.1 open函数2.2 close函数2.3 read函数2.4 write函数2.5 lseek函数 三、示例代码总结 前言 在Linux系统中&#xff0c;C语言通过系统调用实现对文件的输入输出&#xff08;I/O&#xff09;操作。系统调用提供了访问操作…

Docker连接Mysql

Docker连接mysql Docker通过云服务器&#xff0c;与本地连接 引言&#xff1a;这个东西我看狂神秒解决&#xff0c;我就试试了&#xff0c;结果G了&#xff0c;花了我两个小时&#xff0c; 希望内容能帮你解决问题 话不多说&#xff0c;直接上内容&#xff1a; navicat连接…

掌握计算机自动化:Pyperclip与CnOCR详细教程(最全使用方法,每行代码都有注释,帮你解决与之有关的所有问题)

文章目录 一、Pyperclip概念二、Pyperclip基础语法三、Pyperclip与文件交互四、Pyperclip生成随机密码五、OCR概念六、CnOCR 基础识别七、CnOCR 不同图片识别 在这个信息化快速发展的时代&#xff0c;高效的信息处理变得尤为关键。Python&#xff0c;作为一门强大的编程语言&am…

[C语言]——分支和循环(4)

目录 一.随机数生成 1.rand 2.srand 3.time 4.设置随机数的范围 猜数字游戏实现 写⼀个猜数字游戏 游戏要求&#xff1a; &#xff08;1&#xff09;电脑自动生成1~100的随机数 &#xff08;2&#xff09;玩家猜数字&#xff0c;猜数字的过程中&#xff0c;根据猜测数据的⼤…

Gartner对未来5年全球信息安全和风险管理市场的预测分析:影响市场的四大因素及对相关产品市场的影响

到 2023 年&#xff0c;信息安全和风险管理市场的最终用户支出将增长至 1850 亿美元&#xff08;现价美元&#xff09;&#xff0c;货币稳定增长率为 13.4%。到2027年&#xff0c;市场规模将达到2870亿美元&#xff0c;按固定汇率计算&#xff0c;2022年至2027年的复合年增长率…