一、创建版本库及 第一次提交
配置git环境变量,告诉git当前用户的姓名和邮件地址 ,配置的用户名和邮件地址将在版本库提交时用到。
#git config --global user.name “KangShuo”
#git config --global user.email 2471781030@qq.com
系统设置一些git别名
例如:
git config --system alias.st status
git config --system alias.ci commit
git config --system alias.co checkout
git config --system alias.br branch
在Git命令输出中开启颜色显示
#git config --global color.ui true
接下来就从一个空目录开始初始化版本库,将这个版本库命名为Demo版本库,这个demo版本库将贯穿本章内容。
为了方便说明,我们使用名为/path/to/my/workspace的目录作为个人的工作区根目录,可以在磁盘创建该目录并设置正确的权限。
1.首先创建个人的工作区根目录
#mkdir –p /path/to/my/workspace
2.然后进到工作区根目录里面创建为demo名称的版本库,进到demo版本库再用git命令对版本库进行创建初始化
#cd /path/to/my/workspace
#mkdir demo
#cd demo
#git init
或者是1.6.5版本以上的git可以直接运行
#git init demo
创建初始化demo版本库后,可以看到git init命令在工作区根目录创建了隐藏目录.git。
[root@localhost demo]# ls -a
. .. .git
[root@localhost demo]#
这个隐藏的.git目录就是 Git版本库。
.git版本库所在的目录为/path/to/my/workspace/demo,它被称为工作区,这里面目前只有一个.git版本库,其他空无一物。
3.下面在工作区中添加一个welcome.txt的测试文件,内容就是一行Hello。
注意:文件一定要创建在工作区根目录中,否则该文件无法添加到版本库中去。
#cd /path/to/my/workspace/demo
#echo “hello” > welcome.txt
4.将这个新建的文件添加到版本库
#git add welcome.txt
5.将这个新建的文件提交到版本库
注意:在提交过程中需要输入提交说明,这个对于Git来说是强制性的。否则配置会更加繁琐。
使用-m参数指定提交说明
#git commit -m “initialized.”
[master(根提交) 36e8a7e] initialized
1 file changed, 1 insertion(+)
create mode 100644 welcome.txt
从上述输出信息来看:
第一行,此提交是提交在名为master的分支上,且是该分支的第一个提交,提交ID36e8a7e
第二行,此次提交修改了一个文件,包含一行的插入
第三行,此次提交创建了新文件welcome.txt
二、为什么工作区根目录下只有一个.git目录?
首先版本库.git位于工作区的根目录下,只有在这一处地方,其余子目录没有任何其跟踪文件或目录,因此Git的这种设计就比传统的版本控制器要方便的多。
传统的版本控制器中的版本库是和工作区分离开的。例如(CVS、SVN等)。
CVS: 缺点是网络传输文件效率较低导致很慢。
信息泄露,如果web服务器的目录下包含了cvs目录,黑客就可以通过扫描cvs/Entries文件得到目录下的文件列表,从而获得他们想要的信息。
SVN:缺点也是网站信息泄露,还有一点是当在工作区目录下针对文件内容进行搜索时,会因为.svn目录下文件的原始拷贝导致搜索结果加倍,使搜索结果混乱。
然而Git这种将版本库放在工作区根目录下的设计使得所有的版本控制操作(除了与其他远程版本库之间的相互操作)都在本地即可完成,无需通过连接网络去执行相关的操作。
Git还提供了一条Git grep命令来更好的搜索工作区的文件内容
#git grep “工作区文件内容搜索”
工作区中包含子目录的时候执行git命令时,如何定位版本库呢?
如果使用strace命令去跟踪执行git status命令时的磁盘访问,会看到沿目录一次向上递归的过程。
#strace -e ‘trace=file’git status
下面实例就是沿目录向上递归的过程
execve("/usr/bin/git", ["git", "status"], [/* 25 vars */]) = 0
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpcre.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libz.so.1", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
open("/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
open("/usr/lib/locale/locale-archive", O_RDONLY|O_CLOEXEC) = 3
getcwd("/root", 4096) = 6
stat(".", {st_mode=S_IFDIR|0550, st_size=4096, ...}) = 0
stat(".git", 0x7fff9fe291c0) = -1 ENOENT (No such file or directory)
access(".git/objects", X_OK) = -1 ENOENT (No such file or directory)
access("./objects", X_OK) = -1 ENOENT (No such file or directory)
stat("..", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0
chdir("..") = 0
stat(".git", 0x7fff9fe291c0) = -1 ENOENT (No such file or directory)
access(".git/objects", X_OK) = -1 ENOENT (No such file or directory)
access("./objects", X_OK) = -1 ENOENT (No such file or directory)
fatal: Not a git repository (or any of the parent directories): .git
+++ exited with 128 +++
上面的操作总是默默的执行,就好像什么也没有发生一样。
那么有什么办法知道git版本库的具体位置呢?又如何能知道工作区的根目录在哪里呢?可以使用Git的底层一个命令来实现。
1.首先进到工作区中建立目录a/b/c,再进入到该目录中。
#cd /path/to/my/workspace/demo/
#mkdir -p a/b/c
#cd /path/to/my/workspace/demo/a/b/c
2. 显示版本库.git目录所在的具体位置
#git rev-parse --git-dir
/path/to/my/workspace/demo/.git
显示工作区根目录
#git rev-parse --show-toplevel
/path/to/my/workspace/demo
3.相对于工作区根目录的相对目录。
#git rev-parse --show-prefix
/a/b/c/
4.显示从当前目录(cd)后退(up)到工作区的根的深度。
#git rev-parse --show-cdup
../../../
传统的版本控系统中的版本库都是和工作区分离的,像git直接把版本库放在工作区这样安全吗?
不安全,如果在工作区执行根删除命令操作时容易把git版本库一起删除掉,再如果将版本库和工作区分开似乎是很安全,可是不要忘了,这时就要引入其他机制以便实现版本库对工作区的追踪。那有没有更好的办法呢?
有,可以使用git克隆,这样可以降低因版本库和工作区混合在一起而导致版本库被破坏的风险
git克隆操作在本机另外的磁盘/目录中,建立git克隆,并在工作区有新的提交时,手动或自动地执行向克隆版本库的推送操作。
如果使用网络协议,还可以实现在其他机器上克隆。这样就更安全了(双机备份)。
三、Git config 命令的各参数有何区别?
1.版本库配置文件(优先级高)
#cd /path/to/my/workspace/demo/
#git config -e
2.全局配置文件
#git config -e --global
3.系统配置
#git config -e --system(优先级最低)
注意:Git配置文件采用的是INI文件格式。
Git config 命令可以用于读取和更改INI配置文件的内容。
例如:
读取core.bare的属性值:
#git config core.bare
例如:
更改或设置INI文件中的某个属性值
#git config a.b something
#git config x.y.z others
从上面可以看出使用git config命令可以非常方便地操作INI文件,实际上可以操作任何的其他的INI文件。
向配置文件test.ini中添加配置:
#GIT_CONFIG=test.ini git config a.b.c.d “hello,world”
从配置文件test.ini中读取配置:
#GIT_CONFIG=test.ini git config a.b.c.d
Hello,world
四、是谁完成的提交?
在一开始就为git设置了全局变量user.name和user.email,如果不设置会有什么结果呢?
删除git全局配置文件中关于user.name和user.email的设置:
#git config --unset --global user.name
# git config --unset --global user.email
上面的两条命令已经将user.name和user.email清空了,执行下面的命令将看不到输出。
# git config user.name
# git config user.email
下面再次尝试一次提交,看看提交的过程会有什么不同,以及提交之后显示的提交者是谁?
--allow-empty:允许执行空白提交
加上这个参数是因为如果对工作区的文件没有进行任何修改,Git默认不会执行提交,使用--allow-empty参数后允许执行空白提交。
执行下面的命令:
[root@localhost ~]# cd /path/to/my/workspace/demo
[root@localhost demo]# git commit --allow-empty -m "who does commit?"
[master ddd4cba] who does commit?
Committer: root <root@localhost.localdomain>
您的姓名和邮件地址基于登录名和主机名进行了自动设置。请检查它们正确
与否。您可以通过下面的命令对其进行明确地设置以免再出现本提示信息:
git config --global user.name "Your Name"
git config --global user.email you@example.com
设置完毕后,您可以用下面的命令来修正本次提交所使用的用户身份:
git commit --amend --reset-author
上面的输出结果是因为没有配置git环境变量所导致的,如果此时查看版本库的日志,会看到有两次提交。
#git log --pretty=fuller
[root@localhost demo]# git log --pretty=fuller
commit 5fd1f9002ac8a76a28afb803322f041712bacc7f
Author: root <root@localhost.localdomain>
AuthorDate: Thu Sep 6 14:28:21 2018 +0800
Commit: root <root@localhost.localdomain>
CommitDate: Thu Sep 6 14:28:21 2018 +0800
who does commit?
commit 36e8a7e26a06d194a56b530848f6dbef7a19df30
Author: KangShuo <2471781030@qq.com>
AuthorDate: Thu Sep 6 09:59:03 2018 +0800
Commit: KangShuo <2471781030@qq.com>
CommitDate: Thu Sep 6 09:59:03 2018 +0800
initialized
为了保证提交时提交者和作者信息的正确性,需要重新恢复user.name和user.email的设置。
# git config --global user.name "KangShuo"
# git config --global user.email 2471781030@qq.com
然后执行下面的命令,重新修改最新的提交,改正作者和提交者的错误信息。
#git commit --amend --allow-empty --reset-author
who does commit?
# 请为您的变更输入提交说明。以 '#' 开始的行将被忽略,而一个空的提交
# 说明将会终止提交。
#
# 提交者: root <root@localhost.localdomain>
#
# 位于分支 master
# 没有修改
--amend参数是对刚刚的提交进行修补,这样就可以改正前面的提交中错误的用户名和邮件地址,而不会产生另外的新提交。
--allow-empty参数使得空白提交被允许。因为要进行的修补提交实际上是一个空白提交。
--reset-author 参数的含义是将Author(提交者)的ID同步修改,否则只会影响提交者(Commit)的ID。使用此参数也会重置AuthorDate信息。
通过日志可以看到,最新提交的作者和提交者的信息已经改正了。
[root@localhost demo]# git log --pretty=fuller
[root@localhost demo]# git log --pretty=fuller
commit b6ae6304ff46aca11f80549a5dc4c584b855e04f
Author: root <root@localhost.localdomain>
AuthorDate: Thu Sep 6 17:36:06 2018 +0800
Commit: root <root@localhost.localdomain>
CommitDate: Thu Sep 6 17:36:06 2018 +0800
who does commit?
commit 7a42747703686bab6d685f107b032655bb25f7e0
Author: KangShuo <2471781030@qq.com>
AuthorDate: Thu Sep 6 15:45:47 2018 +0800
Commit: KangShuo <2471781030@qq.com>
CommitDate: Thu Sep 6 15:45:47 2018 +0800
who does commit?
commit 36e8a7e26a06d194a56b530848f6dbef7a19df30
Author: KangShuo <2471781030@qq.com>
AuthorDate: Thu Sep 6 09:59:03 2018 +0800
Commit: KangShuo <2471781030@qq.com>
CommitDate: Thu Sep 6 09:59:03 2018 +0800
initialized
五、随意设置提交者姓名,是否不太安全?
像Git这样的分布式版本控制系统,可以随心所欲地设定提交者,这似乎太不安全了。
当然这也是分布式控制系统的特性,可以让每个人都成为git版本库的主人,但是团队合作时候就必须需要授权才可以,作为提交者是不应该随意改变配置变量的。
Redmine是一款实现需求管理和缺陷跟踪的项目管理软件,可以与git版本库实现整合。Git的提交可以直接关闭Redmine上的Bug,同时Git的提交还可以反映出项目成员的工作进度。
Redmine中的用户 (项目成员)用一个ID作标识,而Git的提交者则用一个包含用户名和邮件地址的字符串,如何将Redmine的用户和Git的提交者相关联呢?
Redmine提供了一个配置界面用于设置二者之间的映射。显然,如果在Git提交时随意变更提交者的姓名和邮件地址,就会破坏Redmine软件中设置好的用户对应关系。
六、命令别名是干什么的?
可以满足用户特殊的使用习惯
实际上别名可以包含命令参数
# git config --global alias.ci "commit -s"
带上参数,在提交过程中自动添加上提交者姓名和邮件地址的签名标识
七、备份所有的工作成果
[root@localhost ~]# cd /path/to/my/workspace/
[root@localhost workspace]# ls
demo
[root@localhost workspace]# git clone demo demo-step-1
正克隆到 'demo-step-1'...
完成。