一、Git命令
1.1 创建Git本地仓库
仓库是进行版本控制的一个文件目录。我们要想对文件进行版本控制,就必须创建出一个仓库出来。创建一个Git本地仓库对应的命令是 git init ,注意命令要在文件目录下执行。
cpp
hrx@lavm-1lzqn7w2w6:~/gitcode$ pwd
/home/hrx/gitcode
hrx@lavm-1lzqn7w2w6:~/gitcode$ git init
我们会发现,当前目录下多出了一个 .git 的隐藏文件,.git 目录是Git来跟踪管理仓库的,不要手动修改这个目录中的文件。
bash
hrx@lavm-1lzqn7w2w6:~/gitcode$ tree .git/
.git/
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 31
│ │ └── e5098c1fa351225c05f9286c124cab9d4beb8e
│ ├── 3b
│ │ └── 18e512dba79e4c8300dd08aeb37f8e728b8dad
│ ├── 75
│ │ └── eb93ca2dadfd16966679a9d5714118c77b6219
│ ├── c5
│ │ └── a5efacb403ff2606d106a60eeee5d0912aafc6
│ ├── e5
│ │ └── 1899e7b30c9f87ee4cf5ba320f9876acb928fd
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
1.2 配置Git
当安装Git后首先要做的事情是设置你的用户名称和e-mail地址,这是非常重要的。配置命令为:
bash
git config [--global] user.name "Your Name"
git config [--global] user.email "email@example.com"
# 把 Your Name 改成你的昵称
# 把 email@example.com 改成邮箱的格式,只要格式正确即可。
其中 --global 是一个可选项。如果使用了这个可选项,表示这台机器上所有的Git仓库都会使用这个配置。如果你希望在不同的仓库中使用不同的 name 或者 e-mail,可以不需要使用 --global选项,但是要注意,执行命令时必须要在仓库中。
查看配置命令为:
bash
git config -l
删除对应的配置命令为:(要注意如果使用可选项创建的配置,删除也需要带上可选项)
bash
git config [--global] --unset user.name
git config [--global] --unset user.email
1.3 认识工作区,暂存区,版本库
工作区:是在电脑上你要写代码或者文件的目录
暂存区:英文叫做 stage 或者 index。一般存放在 .git 目录下的 index 文件(.git/index)中,我们把暂存区有时叫做索引(index)。注意,在刚开始创建一个仓库时,是没有这个目录的,只有在我们添加了一个文件后,在仓库中才会有这个目录。
版本库:又名仓库,英文名叫做repository。工作区有一个隐藏目录 .git,他不算工作区,而是Git的版本库。这个版本库里面的所有文件都可以被Git管理起来,每一个文件的修改、删除,Git都能跟踪,以便在任何时候都可以追踪历史,或者在将来的某一恶搞时刻可以"还原"。
下面这张图展示了工作区、暂存区和版本库之间的关系:
图中左侧为工作区,右侧为版本库。Git的版本库里存放了很多东西,其中最重要的就是暂存区。
在创建Git版本库时,Git会为我们自动创建一个唯一的master分支,以及指向master的一个指针叫做 HEAD。
当对工作区修改(或者新增)的文件执行 git add 命令时,暂存区目录树的文件索引会被更新。
当执行提交操作 git commit 时,master分支会做相应的更新,可以简单理解为暂存区的目录树才会被真正写入到版本库中。
由上述描述我们便能得知:通过新建或者粘贴进目录的文件,并不能称之为向仓库中新增文件,而只是在工作区新增了文件。必须要通过使用 git add 和 git commit 命令才能将文件添加到仓库中进行管理。
1.4 添加文件 ------ 场景一
在包含 .git 的目录下,新建一个ReadMe文件,我们可以使用 git add 命令可以将文件添加到暂存区:
bash
添加一个或者多个文件到暂存区中:git add [file1] [file2] ...
添加指定目录到暂存区中,包括子目录:git add [dir]
添加当前目录下的所有文件改动到暂存区:git add .
再使用 git commit 命令将暂存区内容添加到本地仓库中:
cpp
提交暂存区中全部内容到本地仓库中:git commit -m "message"
提交暂存区的指定文件到仓库区:git commit [file1] [file2] ... -m "messsage"
注意 git commit 后面的 -m选项,要跟上描述本次提交的message,由用户自己完成,这部分内容绝对不能省略,并要好好描述。是用来记录你的提交细节,是给我们程序员看的。
当我们将已经写好的代码直接提交给本地仓库后,我们可以使用 git log 命令爱查看历史提交记录。该命令显示的是从最近到最远的体检日志,并且可以看到我们 commit 时的日志消息。如果觉得输出信息太多,我们可以加上 --pretty=oneline 参数。
cpp
显示提交日志的命令:git log --pretty=oneline
需要说明的是,我们看到的一大串类似于 23807c5.....56eed6 的是每一次提交的 commit id(版本号),Git的 commit ID不是 1,2,3......递增的数字,而是一恶搞SHAI计算出来的一个非常大的数字,用十六进制表示(你看到的 commit id 和我的肯定不一样,以你自己的为主)。
1.5 查看 .git 文件
先来看一看我们的 .git 的目录结构:
cpp
hrx@lavm-1lzqn7w2w6:~/gitcode$ tree .git/
.git/
├── branches
├── COMMIT_EDITMSG
├── config
├── description
├── HEAD
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── prepare-commit-msg.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 31
│ │ └── e5098c1fa351225c05f9286c124cab9d4beb8e
│ ├── 3b
│ │ └── 18e512dba79e4c8300dd08aeb37f8e728b8dad
│ ├── 75
│ │ └── eb93ca2dadfd16966679a9d5714118c77b6219
│ ├── c5
│ │ └── a5efacb403ff2606d106a60eeee5d0912aafc6
│ ├── e5
│ │ └── 1899e7b30c9f87ee4cf5ba320f9876acb928fd
│ ├── e6
│ │ └── 9de29bb2d1d6434b8b29ae775ad8c2e48c5391
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
index 就是我们的暂存区,add后的内容都是添加到这里的
HEAD 就是我们的默认指向 master 分支的指针
cpp
cat .git/HEAD
ref: refs/heads/master
然而默认的 master 分支,其实就是:
cpp
cat .git/refs/heads/master
23807c536969cd886c4fb624b997ca575756eed6
object 作为Git的对象库,里面包含了创建的各种版本库对象以及内容。当执行 git add 命令时,暂存区的目录树被更新,同时工作区修改(或者新增)的文件内容被写入到对象库中的一个新的对象中,就位于".git/objects"目录下,让我们来看一看这些对象是什么:
cpp
ls .git/objects/
23 83 8f 9c c6 e6 info pack
查找object时要将commit id 分为2部分,其前2位是文件夹名称,后38位是文件名称。当我们找到这个文件之后,一般不能直接看到里面是什么,该类文件是经过sha(安全哈希算法)加密过的文件,好在我们可以使用 git cat-file 命令来查看版本库对象的内容:
cpp
git cat-file -p 23807c536969cd886c4fb624b997ca575756eed6(commit id)
总结一下,在本地的git仓库中,有几个文件或者目录很特殊:
- index暂存区:git add 后会更新该内容
- HEAD:默认指向master分支的一个指针
- refs/heads/master:文件里面保存当前 master 分支的最新的 commit id
- object:包含了创建的各种版本库对象以及内容,可以简单理解为放了 git 维护的所有修改
1.6 添加文件 ------ 场景二
当我们创建了多个文件的时候,我们也需要使用add命令将所有创建的文件添加进暂存区中,这样我们使用git commit 命令的时候会将暂存区中内容添加到本地仓库中。
1.7 修改文件
Git 比其他版本控制系统设计的优秀,是因为Git跟踪管理的是修改,而并不是文件。什么是修改呢??比如你新增了一行,这就是修改,删除了一行,也是一个修改,更改了某些字符,也是一个修改,甚至创建一个文件,也是一个修改。
当我们修改了ReadMe文件后,此时,在仓库中的ReadMe文件和工作区中的ReadMe文件是不同的,如何查看当前仓库的状态呢??我们可以使用 git status 命令开来查看在上次提交之后是否有对文件进行再次修改。
bash
git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: ReadMe
no changes added to commit (use "git add" and/or "git commit -a")
我们可以使用 git diff [file] 命令用来显示暂存区和工作区文件的差异,显示的格式正是Unix通用的diff格式,也可以使用 git diff HEAD -- [file] 命令来查看版本库和工作区文件的区别。
bash
git diff [file]
git diff HEAD -- [file]
1.8 版本回退
之前我们也提到过,Git能够管理文件的历史版本,这也是版本控制器重要的能力。如果有一天你发现之前的工作出现了很大的问题,需要在某一个特定的历史版本重新开始,这个时候,就需要版本回退的功能了。
执行 git reset 命令用于回退版本,可以指定退回某一次提交的版本。需要解释一下"回退"的本质是要将版本库中的内容进行回退,工作区或者暂存区是否回退由命令参数决定:
bash
git reset 命令语法格式为:git reset [--soft | --mixed | --hard] [HEAD]
--mixed为默认选项,使用时可以不用带该参数。该参数将暂存区的内容退回为执行提交版本内容,工作区文件保持不变。
--soft参数对于工作区和暂存区的内容都不变,只是将版本库回退到某一个指定的版本。
--hard参数将暂存区和工作区都退回到指定版本。切记工作区有未提交的代码时不要使用这个命令,因为工作区会回滚,你没有提交的代码就再也找不回了,所以使用该参数前一定要慎重。
HEAD说明:
可以直接写成commit id,表示指定退回的版本
HEAD表示当前版本
HEAD^表示上一个版本
HEAD^^表示上上一个版本
以此类推
也可以使用 ~ + 数字 表示:
HEAD~0 表示当前版本
HEAD~1 表示上一个版本
HEAD~2 表示上上一个版本
以此类推
如果我们在回退版本之后,我们反悔了,想要拿到最开始的版本需要怎么办??我们可以继续使用 git reset 命令,回退到最开始的版本,但是我们必须要拿到最开始版本的commit id 去指定回退的版本。
但是我们看到了 git log 并不能打印出最开始版本的 commit id,运气好的话我们可以从终端上去找找之前的记录,运气不好的话 commit id已经被我们弄丢了。
Git还提供了一个 git reflog 命令能补救一下,该命令用来记录本地的每一次命令。
bash
git reflog
14c12c3 (HEAD -> master) HEAD@{0}: reset: moving to
14c12c32464d6ead7159f5c24e786ce450c899dd
d95c13f HEAD@{1}: commit: add version3
14c12c3 (HEAD -> master) HEAD@{2}: commit: add version2
cff9d1e HEAD@{3}: commit: add version1
94da695 HEAD@{4}: commit: add modify ReadMe file
23807c5 HEAD@{5}: commit: add 3 files
c614289 HEAD@{6}: commit (initial): commit my first file
这样,你就可以很方便地找到你的所有操作记录了,但是 d95c13f 这个是什么东西?这个是最开始版本的 commit id 的部分。没错,Git版本回退的时候,也可以使用部分 commit id 来代表目标版本。
值得说的是,Git的版本回退速度非常快,因为Git在内部有一个指向当前分支(此处是master)的HEAD指针,refs/heads/master 文件里保存当前 master 分支的最新 commit id。当我们在回退版本的时候,Git仅仅是给 refs/heads/master 中存储了一个特定的版本,如下图所示:
1.9 撤销修改
1.9.1 情况一:对于工作区的代码,还没有进行add
我们有两种方法去执行撤销修改:第一种方法是直接删除当前工作区新增的代码;但是如果我们写的代码很长怎么办??第二种方法是:Git为我们提供了更好的方法,我们可以使用 git checkout -- [file] 命令让工作区的文件回到最近一次 add 或者 commit 时的状态。需要注意 git checkout -- [file]命令中的 -- 很重要,切记不要省略,一旦省略,该命令就变为其他意思了。
bash
git checkout -- [file]
1.9.2 情况二:对于已经add的代码,还没有进行commit
如果我们使用add命令后将代码保存到暂存区后,我们应该怎么撤销呢?
第一种方法:让我们来回忆一下学过的 git reset 回退命令,该命令如果使用 --mixed 参数,可以将暂存区的内容退回为指定的版本内容,但是工作区的文件保持不变,那么我们就可以回退暂存区中的内容了!!!
bash
# --mixed 是默认参数,使⽤时可以省略
hyb@139-159-150-152:~/gitcode$ git reset HEAD ReadMe
Unstaged changes after reset:
M ReadMe
git checkout -- [file]
第二种方法:我们可以直接使用 --hard 参数直接进行全部回退。
1.9.3 已经add的代码,并且也commit了
不要担心,我们可以 git reset --hard HEAD^ 回退到上一个版本!不过,这是有条件的,就是你还没有把自己的本地版本库推送到远程。一旦我们推送到远程就废了。
1.10 删除文件
在Git中,删除也是一个修改操作,我们实战一下,如果要删除 file5 文件,怎么办?
bash
~/gitcode$ ls
file1 file2 file3 file4 file5 ReadMe
~/gitcode$ rm file5
如果我们直接删除是没有用的,git status 命令会立刻告诉你哪些文件被删除了
此时,工作区和版本库就不一致了,要删除文件,目前除了要删工作区的文件,还要清除版本库的文件。
一般到这里,有两种可能:
- 确实要从版本库中删除该文件
- 不小心删错了
对于第二种情况,很明显误删了,需要使用 Git 进行恢复,删除也是修改:
bash
git checkout -- file5
对于第一种情况,很明显是没有删完,我们只删除了工作区的文件。这个时候就需要使用 git rm 将文件从暂存区和工作区中删除,并且 commit:
bash
git rm file5
git commit -m"deleted file5"
二、分支管理
2.1 理解分支
在版本回退里,每一次提交,Git都把他们串成一条时间线,这条时间线就可以理解为是一个分支。截止到目前,只有一条时间线,在Git中,这个分支叫做主分支,即master分支。
再来理解一下HEAD,HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
每一次提交 ,master分支都会向前移动一步,这样随着你的不断提交,master分支的线也越来越长,而HEAD只要一直指向master分支即可。
2.2 创建分支
Git支持我们查看或者创建其他分支,我们来创建第一个自己的分支,对应的命令为:
bash
git branch #查看当前本地所有分支
git branch dev #新建分支dev
当我们创建新的分支后,Git新建了一个指针叫做dev,*表示当前HEAD指向的分支是master分支。
我们可以使用一张图来总结:
2.3 切换分支
那么如何切换分支呢??使用 git checkout 命令即可完成切换,命令如下:
bash
git checkout dev
我们可以进行在dev分支上进行修改文件,当我们将修改的文件进行add和commit操作后,我们来切换到master分支,发现在master分支下,我们没有看见我们新修改的文件,但是在dev分支下,新修改的文件还在,我们来看一看dev分支和master分支的指向,发现两者指向的提交不一样。
这里就明白了,因为我们是在dev分支上提交的,但是master分支此刻的提交点并没有改变,此时的状态图如下所示:
当切换到master分支时,HEAD就指向了master,当然看不到提交了。
2.4 合并分支
为了在master主分支上看到新的提交,就需要将dev分支合并到master分支,命令如下:
bash
git branch
git checkout master # 切换到 master 上进行合并
git merge dev # 合并 dev 分支
git merge 命令用于合并指定分支到当前分支。合并后,master就能看到dev分支提交的内容了。此时的状态如下图所示:
Fast-forward 代表"快进模式",也就是直接把master指向dev的当前提交,所以合并速度非常快。当然,也不是每次合并都能 Fast-forward。
2.5 删除分支
合并完成后,dev分支对于我们来说就没有用了,那么dev分支就可以被删除掉,注意如果当前正处于某一个分支下,就不能删除当前分支,命令如下:
bash
~/gitcode$ git branch
* dev
master
hyb@139-159-150-152:~/gitcode$ git branch -d dev
error: Cannot delete branch 'dev' checked out at '/home/hrx/gitcode'
但是可以在其他分支下删除当前分支,命令如下:
bash
:~/gitcode$ git checkout master
Switched to branch 'master'
:~/gitcode$ git branch -d dev
Deleted branch dev (was bdaf528).
:~/gitcode$ git branch
* master
此时的状态图如下图所示:
因为创建、合并和删除分支非常快,所以Git鼓励你使用分支完成某一个任务,合并后再删除分支,这和直接在master分支上工作的效果是一样的,但是过程更加安全。
2.6 合并冲突
但是,在实际分支合并的时候,并不是想合并就能合并成功的,有时候可能会遇到代码冲突的问题。为了演示这个问题,创建一个新的分支dev1,并切换到目标文件,我们可以使用 git chechout -b dev1 一步完成创建并切换的动作,命令如下:
bash
git chechout -b dev1
当我们在master和dev1下都进行修改文件,两个分支都分别有自己的提交,状态就会如下图所示:
在这种情况下,Git只能试图把各自的修改合并起来,但是这种合并就可能会有冲突,发现有文件有冲突后,可以直接查看文件内容,要注意的是Git会用 <<<<<<<<<<<<<<<<<<, ================,>>>>>>>>>>>>>>>>>> 来标识出不同分支的冲突内容, 此时我们必须要手动调整冲突代码,并需要再次提交修正后的结果(一定要再次提交)!!!
到这里冲突就解决完成了,此时的状态就变成了:
用带参数的 git log 也可以看到分支的合并情况,命令如下所示:
bash
git log --graph --pretty=oneline --abbrev-commit
2.7 分支管理策略
通常合并分支时,如果可能,Git会采用Fast forward 模式。在这种模式下,删除分支后,查看分支历史时,会丢掉分支信息。看不出最新提交的到底是merge进来的还是正常提交的。
但是在合并冲突部分,我们也可以看到通过解决冲突文件,会再进行一次新的提交,得到的最终状态为下图所示:
那么这就不是Fast forward模式了,这样的好处是,从分支历史上就可以看出分支信息。
Git支持我们强制禁用Fast forward模式,那么就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
请注意 --no-ff 参数,表示禁用 Fast forward 模式。禁用 Fast forward 模式后合并会创建一个新的commit,所以加上 -m 参数,把描述写进去。
bash
git merge --no-ff -m "message" dev2;
可以看到,不使用 Fast forward 模式merge后就会像这样一样:
所以在合并分支时,加上 --no-ff 参数就可以使用普通模式合并了,合并的历史有分支,能看出来曾经做过合并,而 Fast forward 合并看不出来曾经做过合并。
2.8 分支策略
在实际开发中,我们应该按照几个基本原则进行分支管理:
首先,master分支应该是非常稳定的,也就是仅仅用来发布新版本的,平时不能在上面进行开发。我们做的开发任务基本都在dev分支中,也就是说,dev分支是不稳定的,等到开发完成之后,我们再将dev合并到master中。
2.9 bug分支
假如我们正在进行dev2分支上的开发,开发到一半,突然发现master分支上面有bug,需要解决。在Git中,每一个bu都可以通过一个新的临时分支来修复,修复后,合并分支,然后将临时分支进行删除。
Git提供了git stash命令,可以将当前的工作区信息进行隐藏,被存储的内容可以在将来某一个时刻恢复出来。
bash
git stash
这样使用git status查看工作区就是干净的(除非没有被Git管理的文件),因此,我们可以放心创建分支来进行修复bug。
我们可以使用 git stash list命令来查看刚才保存的工作现场保存到哪里了??
bash
git stash list
工作现场还在,Git把stash内容存在某一个地方了,但是需要恢复一下,如何恢复现场呢??我们可以使用git stash pop 命令,恢复的同时会把stash也进行删除。
bash
git stash pop
另外,恢复现场也可以采用 git stash apply 恢复,但是恢复后,stash 内容并不删除,你需要使用 git stash drop 来删除。
但是我们注意到了,修复bug的内容并没有在dev2上显示,此时的状态图为:
我们不能在master分支上进行合并,我们需要在dev2的分支上进行合并,因为在合并代码的过程中,会有风险和冲突的出现,这些风险和冲突需要我们手动进行解决,但是在解决的过程中,我们也会有风险和冲突的出现,因此,我们不能直接在master分支中进行合并代码,我们需要在dev分支上进行合并代码,最后检测没有问题后,我们再将代码合并到master分支上。
2.10 删除临时分支
在软件开发中,一直会有很多的新的功能要不断被添加进去,在添加一个新的功能时,我们肯定不希望因为一些实验性质的代码将主分支搞乱了,所以,我们每添加一个新功能时,最好可以创建一个新的分支,我们称之为feature分支开发,在上面开发,完成后,合并,最后删除该feature分支。
可是,如果我们今天正在某一个feature分支上开发了一半,被产品经理突然叫停,要停止新的开发,所以这个feature分支必须要被销毁,这个时候使用传统的 git branch -d 命令删除分支的方法是不正确的,我们需要使用新的删除分支的方法:
bash
git branch -D dev
总结一下:
分支在实际上有什么作用呢??我们可以将一个大的项目分割成多个小的功能模块,每一个功能模块都可以分给不同的人进行开发,最后当我们开发完毕之后,我们再一次进行合并到主分支中,这样,即安全,又不影响别人工作。并且 Git无论创建、切换和删除分支,Git都能在1秒之内就可以完成。
三、远程操作
3.1 理解分布式版本控制系统
我们目前所说的所有内容(工作区,暂存区,版本库等等)都是在本地上!!也就是说在你的计算机中。但是现在的Git是分布式版本控制系统!!!我们需要来进行理解一下:
我们每一个人的电脑上都是一个完整的版本库,这样你工作的时候,就不需要联网了,因为版本库就在你自己的电脑中。既然每一个人的电脑上都有一个完整的版本库,那么多人是如何进行协作的呢??比如说,你在你自己的电脑中修改了文件A,你的同事在他的电脑中也修改了文件A,这时,你们之间只需要将各自的修改推送到对方,就可以互相看到对方的修改了。
分布式版本控制系统的安全性要高的多,因为每一个人的电脑里都有一个完整的版本库,某一个版本库丢失都不要紧,随便从其他人那里复制一份即可。
在实际使用分布式版本控制系统的时候,通常充当一个中央服务器的电脑,但是这个服务器的作用仅仅是用来方便交换大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
3.2 克隆远程仓库
克隆、下载远端仓库到本地,需要使用 git clone 命令,后面跟上我们的远端仓库的链接,远端仓库的链接可以从仓库中找到。
在克隆远程仓库的时候,我们可以选择两种协议:SSH协议和HTTPS协议,SSH协议使用了公钥加密和公钥登录机制,体现了其实用性和安全性,使用此协议需要将我们的公钥放上服务器,有Git服务器进行管理。使用HTTPS方式时,没有要求,可以直接克隆下来。
3.3 向远程仓库推送
本地已经 clone 成功远程仓库后,我们便可以向仓库中提交内容,先创建出一个文件:
提交时要注意,如果我们之前设置过全局的name和e-mail,这两项配置需要和gitee上配置的用户名和邮箱一致,否则就会出错。或者从来没有设置过全局的name和e-mail,那么我们第一次提交时也会进行报错。这就需要我们重新配置。
到这里,我们已经将内容提交到本地仓库中,如何将本地仓库的内容推送到远程仓库呢??需要使用 git push 命令。该命令用于将本地的分支版本上传到远程进行合并,命令格式如下所示:
bash
git push <远程主机名> <本地分⽀名>:<远程分⽀名>
# 如果本地分⽀名与远程分⽀名相同,则可以省略冒号:
git push <远程主机名> <本地分⽀名>
如果,现在远程仓库的版本要领先于本地仓库的版本时,为了使本地仓库保持最新的版本,我们需要拉取一下远端代码,并合并到本地。Git提供了git pull 命令,该命令用于从远端获取代码并合并本地的版本。命令格式如下:
bash
git pull <远程主机名> <远程分⽀名>:<本地分⽀名>
# 如果远程分⽀是与当前分⽀合并,则冒号后⾯的部分可以省略。
git pull <远程主机名> <远程分⽀名>
3.4 配置Git
3.4.1 忽略特殊文件
在日常开发中,我们有一些文件不想或者不应该提交到本地,比如保存了数据库密码的配置文件,那么git应该怎么知道呢??在GIt工作区的根目录下创建一个特殊的 .gitignore 文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件。
我们可以在创建仓库的时候勾选添加 .gitignore 文件,那么如果当时在创建仓库的时候没有勾选这个选项,我们可以在工作区创建一个也是可以的。
我们如果想要忽略以 .so 或者 .inii 结尾的所有文件,.gitignore 文件的内容如下:
cpp
# 省略选择模本的内容
...
# My configurations:
*.ini
*.so
我们也可以不排除指定文件,可以在 .gitignore 文件中添加一条例外规则:
cpp
# 排除所有 . 开头的隐藏文件:
.*
# 不排除.gitignore文件
!.gitignore
3.4.2 给命令配置别名
在我们使用git的期间,有一些命令的长度实在有点长,我们可以使用一个命令来进行简化:
举一个例子:将git status 简化为 git st,对应的命令为:
cpp
git config --global alias.st status
--global 参数是全局参数,也就是这些命令在这台电脑的所有Git仓库下都可以使用。如果不加这个参数,那么只针对当前的仓库有作用。
四、标签管理
4.1 理解标签
标签 tag,可以简单地理解为是对某次 commit 的一个标识,相当于起了一个别名。例如,在项目发布某一个版本的时候,针对最后一次 commit 起了一个 v1.0 这样的标签来标识里程碑的意义。
那么标签有什么用呢?相对于难以记住的 commit id,tag 很好地解决了这个问题,因为 tag 标签一定要给一个让人记住的,且有意义的名字。当我们需要回退到某一个重要的版本时,直接使用标签就能很快地定位。
4.2 创建标签
在 Git 中打标签非常简单,首先,切换到需要打标签的分支上:
git branch
* master
然后敲命令 git tag [name] 就可以打上一个新标签:
bash
git tag v1.0 // 注意这样是在最新的版本打上标签
可以使用命令 git tag 查看所有标签:
bash
git tag
v1.0
默认标签是打在最新提交的 commit 上的。那么如何在指定的 commit 上打标签呢?方法是找到历史提交的 commit id,然后打上就可以了,命令如下:
bash
git log --pretty=oneline --abbrev-commit // 查看历史记录
97811ab (HEAD -> master, tag: v1.0, origin/master, origin/HEAD) add .gitignore
60e6b0a update README.md.
7ce3183 create file.txt
c6ce3f0 Initial commit
// 对于Initial commit 这次提交打上标签
git tag v0.9 c6ce3f0
git tag
v0.9
v1.0
注意:标签并不是按时间顺序列出的,而是按字母排序的。
我们可以使用 git show [tagname] 查看标签信息:
bash
git show v1.0
commit 97811abd1d43774aeb54fee32bf4fc76b2b08170 (HEAD -> master, tag: v1.0,
origin/master, origin/HEAD)
Author: hyb91 <2689241679@qq.com>
Date: Fri May 12 17:27:06 2023 +0800
add .gitignore
diff --git a/.gitignore b/.gitignore
...
git还提供了可以创建带有说明的标签,用 -a 指定标签名, -m 指定说明文字,格式为:
bash
git tag -a [name] -m "xxx" [commit_id]
另外,打完标签之后,我们可以使用 tree .git 命令来查看一下本地仓库有什么变化??
bash
tree .git
4.3 操作标签
如果标签打错了,也可以删除:
bash
git tag -d v0.9
Deleted tag 'v0.9' (was c6ce3f0)
因为创建的标签都只从存储在本地。所以,打错的标签可以在本地安全删除。
如果要推送到某一个标签到远程,使用命令 git push origin <tagname>,命令如下所示:
bash
git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:hyb91/git_teaching.git
* [new tag] v1.0 -> v1.0
当然,如果本地有很多标签,也可以一次性的全部推送到远端:
bash
git push origin --tags
如果标签已经推送到远程,要删除远程标签就会麻烦一些,先从本地删除:
bash
git tag -d v1.0
然后,从远程删除。删除命令也是 push。但是格式如下:
bash
git push origin :refs/tags/v1.0
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:hyb91/git_teaching.git
- [deleted] v1.0
五、Git实战场景 ------ 多人协作
5.1 多人协作一
5.2 多人协作二
5.3 远端分支删除后,本地 git branch -a 依然能看到的解决方法
当前我们已经删除了远程的几个分支,使用 git branch -a 命令可以查看所有本地分支和远程分支,但是发现很多在远程仓库中已经删除的分支在本地依然可以看到。
我们可以使用 git remote show origin 命令来查看remote地址,远程分支,还有本地分支与之对应的关系信息。
bash
git remote show origin
我们可以使用 git remote prune origin 命令来删除那些在远程仓库中不存在的分支。
bash
git remote prune origin
六、企业级开发模型
6.1 讲一个故事
6.2 系统开发环境
对于开发人员来说,在系统开发过程中最常用的几个环境必须要了解一下:
- 开发环境:开发环境是程序员专门用于日常开发的服务器。为了开发调试方便,一般打开全部错误报告和测试工具,是最基本的环境。
- 测试环境:一个程序在测试环境工作不正常,那么肯定不能将其发布在生产机中。该环境是开发环境到生产环境的过渡环境。
- 预发布环境:该环境是为了避免因测试环境和线上环境的差异等带来的缺陷漏测⽽设⽴的⼀套环境。 其配置等基本和⽣产环境⼀致,⽬的是能让我们发正式环境时更有把握!所以预发布环境是你的产 品质量最后⼀道防线,因为下⼀步你的项⽬就要上线了。要注意预发布环境服务器不在线上集成服务器范围之内,为单独的⼀些机器。
- ⽣产环境:是指正式提供对外服务的线上环境,例如我们⽬前在移动端或PC端能访问到的APP都生产环境。
6.3 Git分支设计规范
环境有了概念之后,那么对于开发人员来说,一般会针对不同的环境来设计分支,如下图所示:
6.3.1 master分支
master作为主分支,该分支为只读且唯一的分支。用于部署到正式发布环境,一般由合并release分支得到的。
主分支作为稳定的唯一的代码库,任何情况下不允许直接在master分支上修改代码。
产品的功能全部实现后,最终在master分支对外发布,另外所在master分支的推送应该打标签(tag)做记录,方便追溯。
master分支不可删除。
6.3.2 release分支
release为预发布分支,基于本次上线所有的feature分支合并到develop分支上,基于develop分支创建,可以部署到测试或者预发布集群。
命令以release/开头,建议的命令规则为: release/version_publishtime。
release分支主要用于提交给测试人员进行功能测试,发布提测阶段,会以release分支代码为基准进行提测。
如果在release分支测试出现问题,需要回归验证develop分支看是否存在此问题。
release分支属于临时分支,产品上线后可以选择删除。
6.3.3 develop分支
develop分支为开发分支,基于master分支创建的只读且唯一的分支,始终保持最新完成以及bug修复后的代码,可以部署到开发环境对应集群中。
可以根据需求大小程度确定是由feature分支合并,还是直接在上面进行开发(非常不建议)。
6.3.4 feature分支
feature分支通常为新功能或者新特性开发分支,以develop分支为基础创建feature分支
命令以feature/开头,建议的命名规则为:feature/useruser_createtime_feature
新特性或者新功能开发完成后,开发人员需要合并到develop分支中
一旦该需求发布上线,需要将其删除
6.3.5 hotfix分支
hotfix分支为先线上bug修复分支或者叫做补丁分支,主要用于对线上的版本进行bug修复。当线上出现紧急问题需要马上修复时,需要基于master分支创建hotfix分支
命令以hotfix/开头,建议的命令规则为:hotfix/user_createtime_hotfix
当问题修复完成后,需要合并到master分支和develop分支并推动到远程。一旦上线,需要将其删除。