Git
Git简介
Git是目前世界上最先进的分布式版本控制系统
Git安装和配置
在官网下载安装程序,然后默认安装即可,安装完成后,在任意文件夹右键可以找到git bash
用户配置
安装完成后,还需要设置,在命令行输入
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
设置机器的用户名和用户邮箱,注意git config命令的--global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。单独的设置不加globle就可以。参考:
it 提供了一个叫做 git config 的工具(译注:实际是 git-config 命令,只不过可以通过 git 加一个名字来呼叫此命令。),专门用来配置或读取相应的工作环境变量。而正是由这些环境变量,决定了 Git 在各个环节的具体工作方式和行为。这些变量可以存放在以下三个不同的地方:
- /etc/gitconfig 文件:系统中对所有用户都普遍适用的配置。若使用 git config 时用 --system 选项,读写的就是这个文件。
- ~/.gitconfig 文件:用户目录下的配置文件只适用于该用户。若使用 git config 时用 --global 选项,读写的就是这个文件。
- 当前仓库的 Git 目录中的配置文件(也就是工作目录中的 .git/config 文件):这里的配置仅仅针对当前仓库有效。每一个级别的配置都会覆盖上层的相同配置,所以 .git/config 里的配置会覆盖 /etc/gitconfig 中的同名变量。
Windows 系统上,Git 会找寻用户主目录下的 .gitconfig 文件。主目录即 HOME 变量指定的目录,一般都是
C:\Documents and Settings$USER。此外,Git 还会尝试找寻 /etc/gitconfig 文件,只不过看当初 Git 装在什么目录,就以此作为根目录来定位。
如果用了 --global 选项,那么更改的配置文件就是位于你用户主目录下的那个,以后你所有的仓库都会默认使用这里配置的用户信息。如果要在某个特定的仓库中使用其他名字或者电邮,只要去掉 --global 选项重新配置即可,新的设定保存在当前仓库的 .git/config 文件里。
如果你是使用 https 进行仓库的推拉,你可能需要配置客户端记住密码,避免每次都输入密码
$ git config --global credential.helper store
文本编辑器配置
接下来要设置的是默认使用的文本编辑器。Git 需要你输入一些额外消息的时候,会自动调用一个外部文本编辑器给你用。默认会使用操作系统指定的默认编辑器,一般可能会是 Vi 或者 Vim。如果你有其他偏好,比如 Emacs 的话,可以重新设置:
$ git config --global core.editor emacs
差异分析工具 还有一个比较常用的是,在解决合并冲突时使用哪种差异分析工具。比如要改用 vimdiff 的话:
$ git config --global merge.tool vimdiff
Git 可以理解 kdiff3,tkdiff,meld,xxdiff,emerge,vimdiff,gvimdiff,ecmerge,和 opendiff 等合并工具的输出信息。当然,你也可以指定使用自己开发的工具。
查看配置信息
要检查已有的配置信息,可以使用 git config --list 命令:
$ git config --list
user.name=Scott Chacon
user.email=schacon@gmail.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
...
有时候会看到重复的变量名,那就说明它们来自不同的配置文件(比如 /etc/gitconfig 和 ~/.gitconfig),不过最终 Git 实际采用的是最后一个。
也可以直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可,像这样:
$ git config user.name
Scott Chacon
创建版本库
版本库即为仓库,英文为repository,可以简单理解成一个目录,这个目录中的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能追踪,以便任何时刻都可以追踪历史,或者在将来的某个时刻可以还原。创建一个库很简单,在一个目录中通过 git init命令即可创建一个git仓库。创建后,目录中会多出一个.git的目录,这个目录是git来跟踪管理版本库的,不能轻易改动。
注意:
- 所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
- Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的,前面我们举的例子只是为了演示,如果要真正使用版本控制系统,就要以纯文本方式编写文件
- 千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误,等等。
创建一个test.txt文件,内容如下
Git is a version control system.
Git is free software.
第一步,用git add命令,让git把文件添加到仓库
git add test.txt
第二步,使用git commit命令告诉git把文件提交到仓库
git commit -m "wrote a file"
git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,git commit执行成功后会告诉你,1 file changed:1个文件被改动(我们新添加的test.txt文件);2 insertions:插入了两行内容。
git add一次可以添加一个或多个文件
git add [file1] [file2] //添加多个文件
git add [dir] //添加指定目录到暂存区,包括子目录
git add . //将当前目录下的所有文件添加到暂存区
版本控制
状态查看
我们已经成功添加并提交了一个test.txt文件,继续修改test.txt文件,改为
Git is a distributed version control system.
Git is free software.
这时运行git status命令结果为
$ 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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
git status命令可以查看git仓库当前的状态,上面的命令输出的含义为,test.txt被修改过,但还没有准备提交的修改。
虽然通过 status可以知道test.txt被修改了,但不知道具体修改的内容,可以通过git diff来查看
$ git diff test.txt
diff --git a/test.txt b/test.txt
index d8036c1..013b5bc 100644
--- a/test.txt
+++ b/test.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
\ No newline at end of file
git diff就是查看difference,显示格式为Uni通用的diff格式,可以从上面的命令输出看到,我们在第一行添加了一个distributed单词。提交修改和提交新文件是一样的两步,第一步是git add
git add test.txt
在执行第二步git commit之前,我们再运行git status查看当前仓库的状态:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
git status告诉我们,将要被提交的修改包括test.txt
第二步就是提交git commit -m
$ git commit -m "add distributed"
[master 9ec8740] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
提交后,再用git status命令查看仓库的当前状态:
$ git status
On branch master
nothing to commit, working tree clean
git告诉我们当前没有需要提交的修改,而且,工作目录是干净的。
版本回退
再修改一次test.txt,改为:
Git is a distributed version control system.
Git is free software distributed under the GPL.
然后提交
git add test.txt
git commit -m "append GPL"
目前,已经有三个版本被提交到了git仓库中了:
版本一:git commit test
Git is a version control system.
Git is free software
版本二:append distributed
Git is a distributed version control system.
Git is free software.
版本三:append GPL
Git is a distributed version control system.
Git is free software distributed under the GPL.
在实际工作中,用git log可以查看每次的改动了什么内容
$ git log
commit 716e6f4972bfaa4b6d3458c8c27239223230f216 (HEAD -> master)
Author: pengrui.niu <pengrui.niu@qunar.com>
Date: Sun Sep 25 23:10:09 2022 +0800
append GPL
commit 9ec8740e5e53fa58f27af087c25bb62059ed4e05
Author: pengrui.niu <pengrui.niu@qunar.com>
Date: Sun Sep 25 22:32:51 2022 +0800
add distributed
commit 5326625fae08b380ceeb27df69e0d97fc7015da4
Author: pengrui.niu <pengrui.niu@qunar.com>
Date: Sun Sep 25 21:48:16 2022 +0800
git commit test
git log命令显示从最近到最远的提交日志,能够看到三次提交,最近一次提交时append GPL,上一次是add distributed,最早的一次是git commit test。在命令后加上--pretty=oneline参数,可以简化信息:
$ git log --pretty=oneline
716e6f4972bfaa4b6d3458c8c27239223230f216 (HEAD -> master) append GPL
9ec8740e5e53fa58f27af087c25bb62059ed4e05 add distributed
5326625fae08b380ceeb27df69e0d97fc7015da4 git commit test
如果想把test.txt回退到上一个版本,也就是 add distributed版本。首先要知道当前是哪个版本,在git中,用HEAD表示当前版本,上一个版本是HEAD^,上上个版本是HEAD^^,往上100个版本是HEAD~100。
把当前版本append GPL回退到上一个版本add distributed,使用git reset命令。
$ git reset --hard HEAD^
HEAD is now at 9ec8740 add distributed
此时用git log查看当前版本库日志
$ git log
commit 9ec8740e5e53fa58f27af087c25bb62059ed4e05 (HEAD -> master)
Author: pengrui.niu <pengrui.niu@qunar.com>
Date: Sun Sep 25 22:32:51 2022 +0800
add distributed
commit 5326625fae08b380ceeb27df69e0d97fc7015da4
Author: pengrui.niu <pengrui.niu@qunar.com>
Date: Sun Sep 25 21:48:16 2022 +0800
git commit test
最新的append GPL已经不见了,此时如果想回到append GPL,窗口没关的话,往上翻,可以通过之前的那个版本的commit id回去,id不需要写全,写前几位就可以。
$ git reset --hard 716e
HEAD is now at 716e6f4 append GPL
但是如果把窗口关了后,再想回到这个版本的话怎么办呢。需要commit id,git提供了一个命令git reflog用来记录每一次的命令:
$ git reflog
716e6f4 (HEAD -> master) HEAD@{0}: reset: moving to 716e
9ec8740 HEAD@{1}: reset: moving to HEAD^
716e6f4 (HEAD -> master) HEAD@{2}: commit: append GPL
9ec8740 HEAD@{3}: commit: add distributed
5326625 HEAD@{4}: commit (initial): git commit test
这样知道commit id后,就可以跳到任意版本了。
工作区和暂存区
工作区(Working Directory):就是电脑里看到的目录,比如gittest2就是一个工作区
版本库(Repository):工作区有一个隐藏的目录.git,这个不算工作区,而是版本库。
git版本库里存了很多东西,其中最重要的就是称为stage(或者较index)的暂存区,还有git为我们自动创建的第一个分支master,以及指向master的第一个指针HEAD。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
管理修改
为什么Git比其他版本控制系统设计得优秀,因为Git跟踪并管理的是修改,而非文件。比如,在test.txt中新加一行Git tracks changes.
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git tracks changes.
然后add,再查看状态
$ git add test.txt
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
然后再修改
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git tracks changes of files.
然后commit
$ git commit -m "git tracks changes"
[master 8fb43d3] git tracks changes
1 file changed, 2 insertions(+), 1 deletion(-)
然后再查看状态
$ 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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
可以看到第二次的修改没有被提交,我们的操作过程为:第一次修改->git add->第二次修改->git commit
因为git管理的是修改,所以,当使用git add命令后,在工作区的第一次修改被放入了暂存区,准备提交,但是在工作区的第二次修改并没有放入暂存区,所以git commit只负责把暂存区的修改提交了,也就是第一次的修改被提交了,第二次的修改不会被提交。怎么提交第二次修改呢?你可以继续git add再git commit,也可以别着急提交第一次修改,先git add第二次修改,再git commit,就相当于把两次修改合并后一块提交了:
第一次修改 -> git add -> 第二次修改 -> git add -> git commit
撤销修改
使用git checkout -- file可以丢弃工作区的修改这里有两种情况:
一种是test.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是test.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
添加一行 Git aaaaaaaa,还没有add到暂存区。
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git tracks changes of files.
Git aaaaaaaa
执行命令git checkout -- test.txt
再次查看文件,文件已经被复原。
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git tracks changes of files.
如果文件修改后,并且已经add到了暂存区,那么如果想把暂存区的修改回退到工作区,可使用命令git reset HEAD <file>,使用HEAD,表示最新的版本。
在文件中添加一行aaa然后add到暂存区,此时查看git status,修改已经被add,还未commit
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: test.txt
此时执行命令git reset HEAD test.txt
$ git reset HEAD test.txt
Unstaged changes after reset:
M test.txt
执行成功,此时在查看状态git status,现在暂存区是干净的,工作区有修改。
$ 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: test.txt
no changes added to commit (use "git add" and/or "git commit -a")
git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。当我们用HEAD时,表示最新的版本。
删除文件
在git中,删除也是一个修改操作,先创建一个新文件testrm.txt并提交
此时在文件夹中把这个文件删除,此时git知道了删除操作,因此工作区和版本库就版本不一致了,执行git status就可以知道那些文件被删除了。
$ git status
On branch master
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
deleted: testrm.txt
no changes added to commit (use "git add" and/or "git commit -a")
如果想从版本库中删除该文件,就使用命令git rm删除,并且commit。如果并不是真的想删除文件,那就可以通过命令git checkout -- testrm.txt将文件恢复到最新版本,但是要小心,只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。