参考源:https://git-scm.com/book/zh
1.6 初次运行 Git 前的配置
1- 安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改。
$ git config --global user.name "John Doe"
$ git config --global user.email [email protected]
2- 配置默认文本编辑器, 主要是用来在提交的时候编辑提交信息的
git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
如果不配置则使用操作系统默认的文本编辑器。
Windows 上 配置记事本为默认编辑器:
git config --global core.editor notepad
1.7 获取帮助
git help
2.1 获取git 仓库
1- 两种获取 Git 项目仓库的方式:
1--将尚未进行版本控制的本地目录转换为 Git 仓库;
2--从其它服务器 克隆 一个已存在的 Git 仓库。
2- 本地初始化仓库
cd xxxx
git init
3- 克隆仓库
git clone
https://xxxxx.git
git clone
命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。
如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名:
$ git clone https://github.com/libgit2/libgit2 mylibgit
4- 添加代码文件并提交
git add file_name
git commit -a -m “some message of this commit”
git add file_name 这条命令会将该文件暂存到git,但是并未提交。如果此后该文件的内容再发生变化,则还可以使用git store file_name 恢复到上一次的暂存的文件。
5- Git 支持多种数据传输协议。 上面的例子使用的是 https://
协议,不过你也可以使用 git://
协议或者使用 SSH 传输协议,比如 user@server:path/to/repo.git
。
2.2 记录每次更新到仓库
1- 工作目录下的每一个文件都不外乎这两种状态:已跟踪 或 未跟踪。
2- git status
命令查看哪些文件处于什么状态。-s 参数为简短输出。
3- 我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式。 来看一个实际的 .gitignore 例子:
$ cat .gitignore
*.[oa]
*~
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。
第二行告诉 Git 忽略所有名字以波浪符(~)结尾的文件。
还需要忽略 log,tmp 或者 pid 目录
要养成一开始就为你的新仓库设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。每一行匹配一类文件或者单个文件或者某个目录或者某类目录。
文件 .gitignore
的格式规范如下:
#
开头的行都会被 Git 忽略。/
)开头防止递归。/
)结尾指定目录。!
)取反。所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号(*
)匹配零个或多个任意字符;[abc]
匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?
)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9]
表示匹配所有 0 到 9 的数字)。 使用两个星号(**
)表示匹配任意中间目录,比如 a/**/z
可以匹配 a/z
、 a/b/z
或 a/b/c/z
等。
我们再看一个 .gitignore 文件的例子:
# 忽略所有的 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf
2.3 查看提交历史
git log
命令
git log
会按时间先后顺序列出所有的提交,最近的更新排在最上面
其中一个比较有用的选项是 -p
或 --patch
,它会显示每次提交所引入的差异(按 补丁 的格式输出)。 你也可以限制显示的日志条目数量,例如使用 -2
选项来只显示最近的两次提交。
注:log 可能会比较长,git 使用less 命令来显示,浏览完成后按 Q键退出浏览。
Log 命令还有很多的参数可以可以搭配使用,比如一些检索的条件。
4- git diff
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异
若要查看已暂存的将要添加到下次提交里的内容,可以用 git diff --staged
命令。 这条命令将比对已暂存文件与最后一次提交的文件差异
5- git commit
每次准备提交前,先用 git status
看下,你所需要的文件是不是都已暂存起来了, 然后再运行提交命令 git commit.
$ git commit
这样会启动你选择的文本编辑器来输入提交说明。
Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候,给 git commit
加上 -a
选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add
步骤。这很方便,但是要小心,有时这个选项会将不需要的文件添加到提交中。
6- Git rm xxx 从暂存区移除xxx文件,可以使用—cached 保留磁盘文件, -f 删除该文件,然后提交。该文件以后都处于未跟踪状态。 注意该操作只影响当前该次提交,该次提交中tree中并不包含该文件了。下次提交的时候,该文件又会被重新标记为未跟踪。但是如果rm 了某个文件,下次checkout的时候并不会恢复该文件。该文件还是存在git 仓库中,只是被git 抛弃了。
2.4 撤销操作
1- amend选项:在前一次提交的基础上编辑重新提交。 从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。
git commit --amend
可以像下面这么使用
$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend
原先提交的信息会在编辑器里
2- git checkout --
2.5 远程仓库的使用
1- 查看你已经配置的远程仓库服务器,可以运行 git remote -v
命令
2- git fetch
访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。必须注意 git fetch
命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。
3- git pull 如果你的当前分支设置了跟踪远程分支, 那么可以用 git pull
命令来自动抓取后合并该远程分支到当前分支。 这或许是个更加简单舒服的工作流程。默认情况下,git clone
命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master
分支(或其它名字的默认分支)。 运行 git pull
通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支。
4- 当你想分享你的项目时,必须将其推送到上游。 这个命令很简单:git push
5-
当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先抓取他们的工作并将其合并进你的工作后才能推送。
6- git remote show
命令查看某一个远程仓库的更多信息
7- 远程仓库的重命名与移除
git remote rename pb paul
git remote remove paul
2.6 打标签
给仓库历史中的某一个提交打上标签,以示重要。
Git tag 显示标签
1- 检索某个版本的tag:
$ git tag -l "v1.8.5*"
v1.8.5
v1.8.5-rc0
v1.8.5-rc1
v1.8.5.5
2- 标签分为轻量标签和附注标签
轻量标签只是某个特定提交的引用,类似一个书签
tag v1.4-lw
3- 附注标签则是存储在 Git 数据库中的一个完整对象,需要提供标签的信息。
git tag -a v1.4 -m "my version 1.4"
4- 后期打标签:
git tag -a v1.2 9fceb02
5- 删除掉你本地仓库上的标签,可以使用命令 git tag -d
6- 如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支:
$ git checkout -b version2 v2.0.0
3.1 Git 分支 - 分支简介
1- Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照 。
2- 在进行提交操作时,Git 会保存一个提交对象(commit object)。 知道了 Git 保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。 首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象, 而由多个分支合并产生的提交对象有多个父对象.
3- git仓库的三种对象: blob 对象(保存着文件快照)、树 对象(记录着目录结构和 blob 对象索引)、提交 对象(包含着指向前述树对象的指针和所有提交信息)。
4-新建分支
git branch -b testing //新建分支并立即切换过去
6- HEAD
它是一个指针,指向当前所在的本地分支(译注:将 HEAD
想象为当前分支的别名)。 在本例中,你仍然在 master
分支上。 因为 git branch
命令仅仅 创建 一个新分支,并不会自动切换到新分支中去。
7- 切换分支
git checkout testing
切换分支会导致本地的文件被替换成另一个分支的文件。在你切换分支之前,保持好一个干净的状态。 有一些方法可以绕过这个问题(即,暂存(stashing) 和 修补提交(commit amending))。Git 会重置你的工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。 Git 会自动添加、删除、修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样。
8- 你可以简单地使用 git log
命令查看分叉历史。 运行 git log --oneline --decorate --graph --all
,它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况。
9- 在切换分支前确保当前分支的所有修改都已经提交,否则会导致切换不成功。
10- 分支合并
假设你已经修正了 #53 问题,并且打算将你的工作合并入 master
分支。
$ git checkout master
Switched to branch 'master'
$ git merge iss53
11- 遇到冲突时的分支合并
如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status
命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件
关于冲突的标记
Git 会在有冲突的文件中加入标准的冲突解决标记:
<<<<<<< HEAD:index.html
=======
>>>>>>> iss53:index.html
这表示 HEAD
所指示的版本在这个区段的上半部分(=======
的上半部分),而 iss53
分支所指示的版本在 =======
的下半部分。 为了解决冲突,你必须选择使用由 =======
分割的两部分中的一个,或者你也可以自行合并这些内容。 例如,你可以通过把这段内容换成下面的样子来解决冲突:
上述的冲突解决方案仅保留了其中一个分支的修改,并且 <<<<<<<
, =======
, 和 >>>>>>>
这些行被完全删除了。 在你解决了所有文件里的冲突之后,对每个文件使用 git add
命令来将其标记为冲突已解决。 一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。
在解决了冲突之后,使用git commit 提交
3.3 分支管理
1- 如果要查看哪些分支已经合并到当前分支,可以运行 git branch –merged
不带*的是可以删除的
3.5 远程分支
远程分支是远程仓库上的分支。如果本地的仓库是从远程clone的,则远程仓库上的分支在本地的仓库中一般以origin/****命名。
Clone 命令的详细解释:
clone
命令会为你自动将远程仓库命名为 origin
,拉取它的所有数据,创建一个指向它的 master
分支的指针,并且在本地将其命名为 origin/master
。 Git 也会给你一个与 origin 的 master
分支在指向同一个地方的本地 master
分支,这样你就有工作的基础。
Origin 的 跟踪
如果要与给定的远程仓库同步数据,运行 git fetch
命令(在本例中为 git fetch origin
)。 这个命令查找 “origin” 是哪一个服务器(在本例中,它是 git.ourcompany.com
), 从中抓取本地没有的数据,并且更新本地数据库,移动 origin/master
指针到更新之后的位置。但是这个命令并不会改变本地的master 分支指针,且本地文件内容并不会发生变化。可以加一条git merge origin/master 即可。其实这两条命令就相当于git pull.
当你想要公开分享一个分支时,需要将其推送到有写入权限的远程仓库上。 本地的分支并不会自动与远程仓库同步——你必须显式地推送想要分享的分支。 这样,你就可以把不愿意分享的内容放到私人分支上,而将需要和别人协作的内容推送到公开分支。
如果希望和别人一起在名为 serverfix
的分支上工作,你可以像推送第一个分支那样推送它。 运行 git push
$ git push origin serverfix
3.6 变基
git checkout experiment
$ git rebase master
git checkout master
$ git merge experiment
这四句命令的作用是:
检出到experiment; 计算当前分支(experiment)基于master 分支的增量;检出到master 分支;合并experiment分支的增量。
使用变基要注意的事项:
对于你已经推送到远程仓库的提交最好不要再执行变基,因为别人可能已经在基于这个提交进行开发了。
4.1 服务器上的GIT协议
一个远程仓库通常只是一个裸仓库(bare repository)——即一个没有当前工作目录的仓库。
Git 可以使用四种不同的协议来传输资料:本地协议(Local),HTTP 协议,SSH(Secure Shell)协议及 Git 协议。
本地协议:
远程仓库处于本机或者共享目录
HTTP协议:
只需要一个 URL 以及服务器只在需要授权时提示输入授权信息
相比 SSH 协议,可以使用用户名/密码授权是一个很大的优势,这样用户就不必须在使用 Git 之前先在本地生成 SSH 密钥对再把公钥上传到服务器。
SSH协议
架设 Git 服务器时常用 SSH 协议作为传输协议
用 SSH 协议的优势有很多。 首先,SSH 架设相对简单 —— SSH 守护进程很常见,多数管理员都有使用经验,并且多数操作系统都包含了它及相关的管理工具。 其次,通过 SSH 访问是安全的 —— 所有传输数据都要经过授权和加密。 最后,与 HTTPS 协议、Git 协议及本地协议一样,SSH 协议很高效,在传输前也会尽量压缩数据。
SSH 协议的缺点在于它不支持匿名访问 Git 仓库。
4.2 在服务器上搭建GIT
第一步:克隆仓库;
Git clone –-bare my_project my_project.git
第二步:将裸仓库拷贝至远程服务器的某个目录
scp -r my_project.git [email protected]:/srv/git
第三步:
此时,其他可通过 SSH 读取此服务器上 /srv/git 目录的用户,可运行以下命令来克隆你的仓库。
$ git clone [email protected]:/srv/git/my_project.git
还有一种方式:
第一步:在远程仓库的机器上初始化一个仓库
$ cd /srv/git
$ mkdir project.git
$ cd project.git
$ git init --bare
Initialized empty Git repository in /srv/git/project.git/
第二步:客户机新建仓库并推送远程仓库:
# on John's computer
$ cd myproject
$ git init
$ git add .
$ git commit -m 'initial commit'
$ git remote add origin git@gitserver:/srv/git/project.git
$ git push origin master
第三步:其他用户克隆:
$ git clone git@gitserver:/srv/git/project.git
$ cd project
$ vim README
$ git commit -am 'fix for the README file'
$ git push origin master
4.3 生成SSH公钥 (授权)
这个是在客户机上需要的步骤
root@kali:~/.ssh# ssh-keygen -o
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:tWim4syScPxcQ1aD2pN7N+78uMvogDX7EdQAV/ueZR4 root@kali
The key's randomart image is:
+---[RSA 3072]----+
| .oo.. |
| ..oo . |
| o o..+ |
| . *. o o |
| . oooS . . E |
|. o o+*..o. = . |
| o +o.+o.o .o . |
| o+o. o =.. |
| .+ .+.B+. |
+----[SHA256]-----+
这条命令在windows机器上也是支持的
生成的id_rsa.pub在用户目录的.ssh 下面。
在用户目录下生成了ssh 公钥之后,下次使用ssh 的时候,会默认使用这个公钥来登录其它的机器。如果没有这个公钥,则会使用用户名和密码登录。
然后在服务器机器上执行如下操作:
$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys
将客户机上的id_rsa.pub 内容附加到/home/git/.ssh/authorized_keys文件中
这样下次该客户机使用ssh RSA登录时就会被允许。
这样做的好处是不需要在服务器机器上去为每一个客户机去新建一个用户,客户机使用git的时候用的都是服务器机上的git 用户的权限,我们要做的是把每一个被允许的用户的RSA公钥添加到服务机git 用户的authorized_keys文件中即可。