Git学习笔记之本地库操作

廖雪峰Git教程学习笔记

前言

关于教程作者

廖雪峰,十年软件开发经验,业余产品经理,精通Java/Python/Ruby/Visual Basic/ObjectiveC等,对开源框架有深入研究,著有《Spring 2.0核心技术与最佳实践》一书,多个业余开源项目托管在GitHub,个人官网:https://www.liaoxuefeng.com

一、Git设置

安装完毕git后,设置个人名字和邮件地址

git config --global user.name "Your Name"
git config --global user.email "email@example.com"

二、创建版本库

版本库又叫仓库,里面的所有文件都可以被Git管理起来,每个文件的修改、删除、跟踪都可以被跟踪,以便实现追踪历史记录还原。
首先,创建一个空文件夹:

$ mkdir gitRepo

第二步,将这个目录变成Git可以管理的仓库

$ cd gitRepo
$ git init
Initialized empty Git repository in /work/gitRepo/.git/

生成的.git目录是用来跟踪管理仓库的,不要轻易修改里面的文件,容易破坏掉git仓库。.get目录默认是隐藏的,通过ls -ah可以查看到
第三步,创建一个文件,然后把它放到Git仓库中。
创建文件一定要在gitRepo或者其子目录中创建,否则Git找不到。创建readme.txt,并添加两端内容:

$ touch readme.txt
$ gedit readme.txt

内容:

Git is a version control system.
Git is free software.

把文件添加到仓库:

$ git add readme.txt

若没有任何显示则表示添加成功,继续使用git命令,将文件提交到仓库:

$ git commit -m "this is a test"
[master (root-commit) 92a925f] this is a test
 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt

在这里,-m后面输入的内容可以理解为对本次提交的解释说明。git commit 成功后1 file changed意味着1个文件被改动即我们新添加的readme.txt文件,2 insertions代表插入了两行内容,即readme.txt内添加的两行内容。
Git添加文件需要两步,具体每一步作用后续有讲到,其中add可以分批add文件,也可以一次add多个文件,而commit则是一次性将所有add的文件提交到仓库。

$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."

三、查看工作区状态

对创建的readme.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 checkout -- <file>..." to discard changes in working directory)
        modified:   readme.txt
no changes added to commit (use "git add" and/or "git commit -a")

git status可以让我们随时掌握仓库目前的状态,从上面的信息可以看到,readme.txt已经被修改了,显示为还没有准备提交的修改。
如果想看到修改的具体内容,要用到git diff命令,diff就是difference的缩写。

$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index e35ea24..86ccde8 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
 Git is free software.

从上面可以看得出来,我们增加了一个distributed单词。接着我们可以放心的将文件提交了。

$ git add readme.txt

使用git status查看一下

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        modified:   readme.txt

可以看到,我们即将提交的是readme.txt。使用git commit进行提交并使用git status查看状态。

$ git commit -m "add distributed"
[master 1ae9018] add distributed
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch master
nothing to commit, working directory clean

查看提交后的状态,显示没有需要提交的修改,而且工作目录是干净的。

四、版本回退

当我们对一个文件不断的修改后,难免因操作失误需要将文件恢复到某个时刻的状态,所以,就像打游戏存档一样,我们可以保存一个快照,在Git中,这个快照被称为commit,当我们误操作后,可以从最近的一个commit恢复,然后继续工作,防止工作成果丢失。
先使用git log 命令查看历史记录

$ git log
commit 1ae901871c9fedda1dd5ad9bd8c952aa244319eb
Author: uidq5232 <Guodong.Chen@desaysv.com>
Date:   Tue Jun 7 19:06:12 2022 +0800
    add distributed
commit 92a925f1281d986aa9f48d7eaa4a74233b8638dc
Author: uidq5232 <Guodong.Chen@desaysv.com>
Date:   Tue Jun 7 17:25:10 2022 +0800
    this is a test

上述代码告诉我们,第一次committhis is a test,第二次为add distributed
使用git log 输出的信息很多,容易眼花缭乱,加上--pretty=oneline参数则简约很多。

$ git log --pretty=oneline
1ae901871c9fedda1dd5ad9bd8c952aa244319eb add distributed
92a925f1281d986aa9f48d7eaa4a74233b8638dc this is a test

还需要注意的是,代码中1ae9…19eb代表的是commit id(版本号),git的commit id是由SHA1计算出来的40位数字,极大的防止在分布式系统中多人协作时版本号冲突。
既然知道了文件的版本号等信息,如何回退到以前的版本呢?在git中,用HEAD表示当前版本,即最新提交的1ae9…19eb,上一个版本就是HEAD^,上上个版本是HEAD^^,当然版本号回退100个也可以用HEAD~100。我们把版本回退到上一个版本,这里用到的是git reset命令。

$ git reset --hard HEAD^
HEAD is now at 92a925f this is a test

当我们再次使用git log查看状态时

$ git log
commit 92a925f1281d986aa9f48d7eaa4a74233b8638dc
Author: uidq5232 <Guodong.Chen@desaysv.com>
Date:   Tue Jun 7 17:25:10 2022 +0800
    this is a test

最新的add distributed已经不见了,但是我们若还想回到那个版本的话,只要窗口没有关掉,add distributed的版本号1ae9…19eb还能找到,就可以指定回到未来的某个版本。

$ git reset --hard 1ae90
HEAD is now at 1ae9018 add distributed

版本号写前几位就可以了,git会自己去找。
当我们不知道未来版本号但是还要回到未来版本时要怎么做那?比如我们要从this is a test回到add distributed要怎么做那,git提供了git reflog 用来记录每一次命令。

$ git reflog
92a925f HEAD@{0}: reset: moving to HEAD^
1ae9018 HEAD@{1}: reset: moving to 1ae90
92a925f HEAD@{2}: reset: moving to HEAD^
1ae9018 HEAD@{3}: commit: add distributed
92a925f HEAD@{4}: commit (initial): this is a test

可以看到,我们从哪个版本回退到另一个版本的历史操作都能找到add distributed的commit id是1ae9018,所以我们可以根据版本号再次回到add distributed版本。

五、工作区和暂存区

工作区:我们创建的gitRepo就是一个工作区。
版本库:工作区内的隐藏目录.git,这个不算工作区,是Git的版本库。
暂存区:GIt版本库中有一个名为stage(或者index)的地方叫做暂存区,当我们执行git add时,文件就被放到了暂存区等待提交。当我们继续执行git commit时,实际上就是把暂存区的所有文件提交到当前分支。
分支:每一次提交Git都会把他串成一条时间线,方便版本回退,这条时间线就是分支,创建版本库时,Git自动为我们创建了第一个分支master,这个分支叫主分支,以及指向master的一个指针HEAD,具体后面详述。
在工作区新添加一个license文件,内容随意,并且对readme.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 checkout -- <file>..." to discard changes in working directory)
        modified:   readme.txt
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        license
no changes added to commit (use "git add" and/or "git commit -a")

上述代码可以看到,readme.txt被修改了但还没有添加到暂存区,license是一个Untracked files,表示还没有被添加过,现在将两个文件添加到暂存区。

$ git add readme.txt license
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        new file:   license
        modified:   readme.txt

再使用commit命令将暂存区的所有修改提交到分支。

$ git commit -m "understand how stage works"
[master f086944] understand how stage works
 2 files changed, 2 insertions(+)
 create mode 100644 license

再次查看状态,提交后如果没有对工作区做任何修改,那么工作区是“干净”的。

$ git status
On branch master
nothing to commit, working directory clean

六、撤销修改

当你不小心在readme.txt中错误的添加了一行内容:

$ cat readme.txt
Git is a version control system.
Git is free software.
Git has a mutable index called stage.
oh,god,i'm a dog.

当然你可以删掉最后一行,手动将文件恢复到上一个版本的状态,但是我们用git status查看时:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
        modified:   readme.txt
no changes added to commit (use "git add" and/or "git commit -a")

Git告诉我们use "git checkout -- <file>..." to discard changes in working directory,所以我们可以使用git checkout -- <file>,丢弃工作区的修改:

$ cat readme.txt
Git is a version control system.
Git is free software.
Git has a mutable index called stage.

果然,文件内容复原了。
git checkout -- <file>就是把文件在工作区的修改全部撤销,这里有两种情况:
一种是只是在工作区修改还没有提交到暂存区,使用该命令可以撤回到和版本库一摸一样的装填。
一种是已经添加到暂存区,又做了修改,使用该命令就回到添加到暂存区的状态。
总之,就是让这个文件回到最近一次git commit或者git add的状态。
git checkout -- file命令中的--很重要,没有--,就变成了“切换到另一个分支”的命令,我们在后面的分支管理中会再次遇到git checkout命令。
假如说我们不光添加了错误的内容还将文件添加到了暂存区:

git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        modified:   readme.txt

幸运的是我们只是添加到了暂存区还没有提交,Git提示我们可以用git reset HEAD <file>把暂存区的修改撤销(unstage),重新弄放回工作区:

$ git reset HEAD readme.txt
Unstaged changes after reset:
M       readme.txt

git reset既可以回退版本,也可以把暂存区的修改回退到工作区,当我们用HEAD时,表示最新的版本。使用git status查看:

$ git status
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)
        modified:   readme.txt
no changes added to commit (use "git add" and/or "git commit -a")

暂存区是干净的,工作区有修改,继续使用之前的git checkout命令丢弃工作区的修改:

$ git checkout -- readme.txt
$ git status
On branch master
nothing to commit, working directory clean

终于,所有修改都被撤销掉了。
如果说你已经commit了,那么就只能使用reset回退到上一个版本,但是如果已经推送到远程仓库,就没有办法了。

小结:
场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout – file。

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

七、删除文件

删除文件的操作实际上就是修改文件,我们新创建一个test.txt到Git并提交:

$ git add test.txt
$ git commit -m "add test.txt"
[master 789e43f] add test.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 test.txt

常规下,我们使用rm命令就可以把文件管理器中的文件删除掉:

$ rm test.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 checkout -- <file>..." to discard changes in working directory)
        deleted:    test.txt
no changes added to commit (use "git add" and/or "git commit -a")

现在你有两个选择,一是确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit

$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master 0e437ff] remove test.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 test.txt

现在,文件就从版本库中被删除了。
另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:

$ git checkout -- test.txt

git checkout其实就是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值