Git基本用法
1.Git初始化
使用Git的第一件事就是设置你的名字和email,这些就是你在提交commit时的签名,每次提交记录里都会包含这些信息。使用git config命令进行配置:
1 |
|
执行了上面的命令后,会在家目录(/home/shiyanlou)下建立一个叫.gitconfig的文件(该文件为隐藏文件,需要使用ls -al查看到).内容一般像下面这样,可以使用vim或cat查看文件内容:
1 |
|
上面的配置文件就是Git全局配置的文件,一般配置方法是 git config –global <配置名称> <配置的值>
如果你像使项目里的某个值与前面的全局设置有区别(例如把私人邮箱地址改为工作邮箱),你可以再项目中使用git config命令不带–global选项来设置,这会再你当前的项目目录下创建.git/config,从而使用针对当前项目的配置。
2.获得一个Git仓库
2.1Clone一个仓库
为了得到一个项目的拷贝,我们需要知道这个项目仓库的地址(Git URL)。Git能在许多协议下使用,所以Git URL可能以ssh://, http(s)://, git://开头。有些仓库可以通过多种协议来访问。
1 |
|
clone操作完成后,会发现/home/shiyanlou/目录多了一个gitproject文件夹,这个文件夹里的内容就是我们刚刚clone下来的代码。由于当前gitproject仅是测试项目,里面仅有一个README.md文件。
1 |
|
细心的同学可以发现在命令提示符 $ 前面多了个 (master)。这是由于实验楼的 Linux 使用的是zsh Shell,zsh 会判断当前的目录是否有 Git 仓库,如果是的话则自动把目前所在的 Git 分支显示在提示符中。Git 分支的概念我们会在稍后介绍。
2.2初始化一个新的仓库
可以对一个已存在的文件夹用下面的命令让它置于Git的版本控制管理之下。
创建代码目录project:
1 |
|
进入到代码目录,创建并初始化Git仓库:
1 |
|
Git会输出:
1 |
|
通过 ls -la 命令会发现project目录下会有一个名叫 .git 的目录被创建,这意味着一个仓库被初始化了。可以进入到 .git 目录查看下有哪些内容。
3.正常的工作流程
Git 的基本流程如下:
- 创建或修改文件
- 使用 git add 命令添加新创建或修改的文件到本地的缓存区(Index)
- 使用 git commit 命令提交到本地代码库
- (可选,有的时候并没有可以同步的远端代码库)使用git push命令将本地代码库同步到远端代码库
3.1创建或修改文件
进入我们刚才建立的 project 目录,分别创建文件 file1,file2,file3:
1 |
|
修改文件,可以使用 vim 编辑内容,也可以直接 echo 添加测试内容。
1 |
|
此时可以使用 git status 命令查看当前 Git 仓库的状态:
1 |
|
可以发现,有三个文件处于 untracked 状态,下一步我们就需要用 git add 命令将他们加入到缓存区(Index)。
3.2使用git add加入缓存区
使用 git add 命令将新建的文件添加到缓存区:
1 |
|
然后再次执行 git status 就会发现新的变化:
1 |
|
你现在为 commit 做好了准备,你可以使用 git diff 命令再加上 –cached 参数,看看缓存区中哪些文件被修改了。进入到 git diff –cached 界面后需要输入 q 才可以退出
1 |
|
如果没有–cached参数,git diff 会显示当前你所有已做的但没有加入到缓存区里的修改。
如果你要做进一步的修改, 那就继续做, 做完后就把新修改的文件加入到缓存区中。
3.3使用git commit提交修改
当所有新建,修改的文件都被添加到了缓存区,我们就要使用 git commit 提交到本地仓库:
1 |
|
需要使用 -m 添加本次修改的注释,完成后就会记录一个新的项目版本。除了用 git add 命令,我们还可以用下面的 -a 参数将所有没有加到缓存区的修改也一起提交,但 -a 命令不会添加新建的文件。
1 |
|
再次输入 git status 查看状态,会发现当前的代码库已经没有待提交的文件了,缓存区已经被清空。
至此,我们完成了第一次代码提交,这次提交的代码中我们创建了三个新文件。需要注意的是如果是修改文件,也需要使用 git add 命令添加到缓存区才可以提交。如果是删除文件,则直接使用 git rm 命令删除后会自动将已删除文件的信息添加到缓存区,git commit 提交后就会将本地仓库中的对应文件删除。
这时如果我们希望将本地仓库关联到远端服务器,我们可以使用 git remote 命令,不同于刚刚的 git clone 命令,直接将远端的仓库克隆下来。
我们当前的仓库是使用 git init 初始化的本地仓库,所以我们需要将本地仓库与远程仓库关联,使用如下命令(需要修改下面的远程仓库地址为自己的仓库地址):
1 |
|
对于上述命令而言,git remote add 命令用于添加远程主机,origin 是主机名,此处我们可以自定义,不一定非要使用 origin,而https://github.com/kinglion580/shiyanlou.git,是我自己的远程仓库,此处 需要替换为自己的远程仓库地址
这个时候如果本地的仓库连接到了远程Git服务器,可以使用下面的命令将本地仓库同步到远端服务器:
1 |
|
4.分支与合并
Git 的分支可以让你在主线(master 分支)之外进行代码提交,同时又不会影响代码库主线。分支的作用体现在多人协作开发中,比如一个团队开发软件,你负责独立的一个功能需要一个月的时间来完成,你就可以创建一个分支,只把该功能的代码提交到这个分支,而其他同事仍然可以继续使用主线开发,你每天的提交不会对他们造成任何影响。当你完成功能后,测试通过再把你的功能分支合并到主线。
4.1创建分支
一个 Git 仓库可以维护很多开发分支。现在我们来创建一个新的叫 experimental 的分支:
1 |
|
运行 git branch 命令可以查看当前的分支列表,以及目前的开发环境处在哪个分支上:
1 |
|
4.2切换分支
experimental 分支是你刚才创建的,master 分支是 Git 系统默认创建的主分支。星号标识了你当工作在哪个分支下,输入 git checkout 分支名 可以切换到其他分支:
1 |
|
切换到 experimental 分支,切换完成后,先编辑里面的一个文件,再提交(commit)改动,最后切换回 master 分支:
1 |
|
查看下 file1 中的内容会发现刚才做的修改已经看不到了。因为刚才的修改时在 experimental 分支下,现在切换回了 master 分支,目录下的文件都是 master 分支上的文件了。
4.3合并分支
现在可以在 master 分支下再作一些不同的修改:
1 |
|
这时,两个分支就有了各自不同的修改,分支的内容都已经不同,如何将多个分支进行合并呢?
可以通过下面的 git merge 命令来合并 experimental 到主线分支 master:
1 |
|
-m 参数仍然是需要填写合并的注释信息。
由于两个 branch 修改了两个不同的文件,所以合并时不会有冲突,执行上面的命令后合并就完成了。
如果有冲突,比如两个分支都改了一个文件 file3,则合并时会失败。首先我们在master分支上修改file3 文件并提交:
1 |
|
然后切换到 experimental,修改 file3 并提交:
1 |
|
切换到 master 进行合并:
1 |
|
合并失败后先用 git status 查看状态,会发现 file3 显示为 both modified,查看 file3内容会发现:
1 |
|
上面的内容也可以使用 git diff 查看,先前已经提到 git diff 不加参数可以显示未提交到缓存区中的修改内容。
可以看到冲突的内容都被添加到了 file3 中,我们使用 vim 编辑这个文件,去掉 Git 自动产生标志冲突的 <<<<<< 等符号后,根据需要只保留我们需要的内容后保存,然后使用 git add file3 和 git commit 命令来提交合并后的 file3 内容,这个过程是手动解决冲突的流程。
1 |
|
4.4 删除分支
当我们完成合并后,不再需要experimental时,可以使用下面的命令删除:
1 |
|
git branch -d只能删除那些已经被当前分支的合并的分支. 如果你要强制删除某个分支的话就用git branch –D
4.5撤销一个合并
如果你觉得你合并后的状态是一团乱麻,想把当前的修改都放弃,你可以用下面的命令回到合并之前的状态:
1 |
|
4.6快速向前合并
还有一种需要特殊对待的情况,在前面没有提到。通常,一个合并会产生一个合并提交(commit), 把两个父分支里的每一行内容都合并进来。
但是,如果当前的分支和另一个分支没有内容上的差异,就是说当前分支的每一个提交(commit)都已经存在另一个分支里了,Git 就会执行一个 快速向前(fast forward)操作;Git 不创建任何新的提交(commit),只是将当前分支指向合并进来的分支。
5.Git日志
5.1查看日志
git log 命令可以显示所有的提交(commit):
1 |
|
如果提交的历史纪录很长,回车会逐步显示,输入 q 可以退出。
git log 有很多选项,可以使用 git help log 查看,例如下面的命令就是找出所有从 “v2.5“ 开始在 fs 目录下的所有 Makefile 的修改(这个只是举例,不用操作):
1 |
|
Git 会根据 git log 命令的参数,按时间顺序显示相关的提交(commit)。
5.2日志统计
如果用 –stat 选项使用 git log,它会显示在每个提交(commit)中哪些文件被修改了, 这些文件分别添加或删除了多少行内容,这个命令相当于打印详细的提交记录:
1 |
|
5.3格式化日志
你可以按你的要求来格式化日志输出。–pretty 参数可以使用若干表现格式,如 oneline:
1 |
|
或者你也可以使用 short 格式:
1 |
|
你也可用 medium,full,fuller,email 或 raw。 如果这些格式不完全符合你的需求, 你也可以用 –pretty=format 参数定义格式。
–graph 选项可以可视化你的提交图(commit graph),会用ASCII字符来画出一个很漂亮的提交历史(commit history)线:
1 |
|
5.4日志排序
日志记录可以按不同的顺序来显示。如果你要指定一个特定的顺序,可以为 git log 命令添加顺序参数。
按默认情况,提交会按逆时间顺序显示,可以指定 –topo-order 参数,让提交按拓扑顺序来显示(就是子提交在它们的父提交前显示):
1 |
|
你也可以用 –reverse 参数来逆向显示所有提交日志。
6.比较内容
下面将学习如何比较提交,分支等内容。
6.1比较提交 - Git diff
现在我们对项目做些修改:
1 |
|
使用 git status 查看当前修改的状态:
1 |
|
可以看到一个文件修改了,另外一个文件添加了。如何查看修改的文件内容呢,那就需要使用 git diff 命令。git diff 命令的作用是比较修改的或提交的文件内容。
1 |
|
上面的命令执行后需要使用 q 退出。命令输出当前工作目录中修改的内容,并不包含新加文件,请注意这些内容还没有添加到本地缓存区。
将修改内容添加到本地缓存区,通配符可以把当前目录下所有修改的新增的文件都自动添加:
1 |
|
再执行 git diff 会发现没有任何内容输出,说明当前目录的修改都被添加到了缓存区,如何查看缓存区内与上次提交之间的差别呢?需要使用 –cached 参数:
1 |
|
可以看到输出中已经包含了新加文件的内容,因为 file1 已经添加到了缓存区。
最后我们提交代码:
1 |
|
提交后 git diff 与 git diff –cached 都不会有任何输出了。
6.2比较分支
可以用 git diff 来比较项目中任意两个分支的差异。
我们首先创建一个新的分支 test,并在该分支上提交一些修改:
1 |
|
然后,我们查看 test 分支和 master 之间的差别:
1 |
|
git diff 是一个难以置信的有用的工具,可以找出你项目上任意两个提交点间的差异。可以使用 git help diff 详细查看其他参数和功能。
6.3更多的比较选项
如果你要查看当前的工作目录与另外一个分支的差别,你可以用下面的命令执行:
1 |
|
你也以加上路径限定符,来只比较某一个文件或目录:
1 |
|
上面这条命令会显示你当前工作目录下的 file1 与 test 分支之间的差别。
–stat 参数可以统计一下有哪些文件被改动,有多少行被改动:
1 |
|
7.分布式的工作流程
7.1分布式的工作流程
你目前的项目在 /home/shiyanlou/gitproject 目录下,这是我们的 Git 仓库(repository),另一个用户也想与你协作开发。他的工作目录在这台机器上,如何让他提交代码到你的 Git 仓库呢?
首先,我们假设另一个用户也用 shiyanlou 用户登录,只是工作在不同的目录下开发代码,实际工作中不太可能发生,大部分情况都是多个用户,这个假设只是为了让实验简化。
该用户需要从 Git 仓库进行克隆:
1 |
|
这就建了一个新的 “myrepo” 的目录,这个目录里包含了一份gitproject仓库的克隆。这份克隆和原始的项目一模一样,并且拥有原始项目的历史记录。
在 myrepo 做了一些修改并且提交:
1 |
|
myrepo 修改完成后,如果我们想合并这份修改到 gitproject 的 git 仓库该如何做呢?
可以在仓库 /home/shiyanlou/gitproject 中把myrepo的修改给拉 (pull)下来。执行下面几条命令:
1 |
|
这就把 myrepo 的主分支合并到了 gitproject 的当前分支里了。
如果 gitproject 在 myrepo 修改文件内容的同时也做了修改的话,可能需要手工去修复冲突。
如果你要经常操作远程分支(remote branch),你可以定义它们的缩写:
1 |
|
git pull 命令等同于执行两个操作: 先使用 git fetch 从远程分支抓取最新的分支修改信息,然后使用 git merge 把修改合并进当前的分支。
gitproject 里可以用 git fetch 来执行 git pull 前半部分的工作, 但是这条命令并不会把抓下来的修改合并到当前分支里:
1 |
|
获取后,我们可以通过 git log 查看远程分支做的所有修改,由于我们已经合并了所有修改,所以不会有任何输出:
1 |
|
当检查完修改后,gitproject 可以把修改合并到它的主分支中:
1 |
|
如果我们在 myrepo 目录下执行 git pull 会发生什么呢?
myrepo 会从克隆的位置拉取代码并更新本地仓库,就是把 gitproject 上的修改同步到本地:
1 |
|
因为 myrepo 是从 gitproject 仓库克隆的,那么他就不需要指定 gitproject 仓库的地 址。因为 Git 把 gitproject 仓库的地址存储到 myrepo 的配置文件中,这个地址就是在 git pull 时默认使用的远程仓库:
1 |
|
如果 myrepo 和 gitproject 在不同的主机上,可以通过 ssh 协议来执行 clone 和pull 操作:
1 |
|
这个命令会提示你输入 shiyanlou 用户的密码,用户密码随机,可以点击实验操作界面右侧工具栏的 SSH直连 按钮查看。
7.2公共git仓库
开发过程中,通常大家都会使用一个公共的仓库,并 clone 到自己的开发环境中,完成一个阶段的代码后可以告诉目标仓库的维护者来 pull 自己的代码。
如果你和维护者都在同一台机器上有帐号,那么你们可以互相从对 方的仓库目录里直接拉所作的修改,git 命令里的仓库地址也可以是本地的某个目录名:
1 |
|
也可以是一个ssh地址:
1 |
|
7.3将修改推到一个公共仓库
通过 http 或是 git 协议,其它维护者可以通过远程访问的方式抓取(fetch)你最近的修改,但是他们没有写权限。如何将本地私有仓库的最近修改主动上传到公共仓库中呢?
最简单的办法就是用 git push 命令,推送本地的修改到远程 Git 仓库,执行下面的命令:
1 |
|
或者
1 |
|
git push 命令的目地仓库可以是 ssh 或 http/https 协议访问。
7.4当推送代码失败时要怎么办
如果推送(push)结果不是快速向前 fast forward,可能会报像下面一样的错误:
1 |
|
这种情况通常是因为没有使用 git pull 获取远端仓库的最新更新,在本地修改的同时,远端仓库已经变化了(其他协作者提交了代码),此时应该先使用 git pull 合并最新的修改后再执行 git push:
1 |
|
8.Git标签
8.1轻量级标签
下面学习 Git 标签相关内容。
我们可以用 git tag 不带任何参数创建一个标签(tag)指定某个提交(commit):
1 |
|
这样,我们可以用stable-1 作为提交 8c315325 的代称。
前面这样创建的是一个“轻量级标签”。
如果你想为一个tag添加注释,或是为它添加一个签名, 那么我们就需要创建一个 “标签对象”。
标签对象
git tag 中使用 -a, -s 或是 -u三个参数中任意一个,都会创建一个标签对象,并且需要一个标签消息(tag message)来为 tag 添加注释。 如果没有 -m 或是 -F 这些参数,命令执行时会启动一个编辑器来让用户输入标签消息。
当这样的一条命令执行后,一个新的对象被添加到 Git 对象库中,并且标签引用就指向了一个标签对象,而不是指向一个提交,这就是与轻量级标签的区别。
下面是一个创建标签对象的例子:
1 |
|
8.2签名的标签
签名标签可以让提交和标签更加完整可信。如果你配有GPG key,那么你就很容易创建签名的标签。首先你要在你的 .git/config 或 ~/.gitconfig 里配好key。
下面是示例:
1 |
|
你也可以用命令行来配置:
1 |
|
现在你可以在创建标签的时候使用 -s 参数来创建“签名的标签”:
1 |
|
如果没有在配置文件中配 GPG key,你可以用 -u 参数直接指定。
1 |
|
蚂蚁🐜再小也是肉🥩!
“您的支持,我的动力!觉得不错的话,给点打赏吧 ୧(๑•̀⌄•́๑)૭”
微信支付
支付宝支付