git

167 阅读4分钟

版本库可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

创建版本库

git init 后 文件夹会产生.git 文件其作用为跟踪管理版本库的。

添加文件

言归正传,现在我们编写一个readme.txt文件,内容如

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

第一步,用命令git add <file name>告诉Git,把文件添加到暂存区:执行上面的命令,没有任何显示,这就对了 git add . 可提交当前仓库中所有文件。

git add a.txt b.txt 可指定多个文件添加至暂存区

第二步,用命令git commit -m <备注>告诉Git,把文件提交到仓库:

$ git commit -m "wrote a readme file"
[master (root-commit) eaadf4e] wrote a readme file
 1 file changed, 2 insertions(+)
 create mode 100644 readme.txt

-m : 本次提交修改的备注

版本穿梭

a文档已提交三次版本

版本一:

我是Ws

版本二:

我是Ws
我爸是Wjm

版本三:

我是Ws
我爸是Wjm
我妈是Wcl

版本回退

前言:打游戏时每通过一关都会手动保存,以便可以在闯关失败时返回上一关卡。 git 也是同理为了防止文件下次改动出错,通过每次commit产生的快照id返回之前的版本。

当文件提交的版本过多且我们需要返回某一版本时,怎么才能查找到其历史版本的快照id囊?

查找历史版本快照

git log可以查看文件的提交的历史记录。

$ git log
commit 1b19a4b1db592f744ee073f64f24b249cd75e04f (HEAD -> master)
Author: ws <1535191556@qq.com>
Date:   Thu Jan 18 10:06:18 2024 +0800

    mather

commit f1ed86a7d60ee360f933878a495b4de2d52b051e
Author: ws <1535191556@qq.com>
Date:   Thu Jan 18 09:46:18 2024 +0800

    father

commit 3e690b17a485537c27a326630529748767ea8243
Author: ws <1535191556@qq.com>
Date:   Thu Jan 18 09:45:43 2024 +0800

    add a.txt

可以看到相关信息,最重要的commit参数为版本快照Id

如果a文档像回退到上一版本,使用 git reset --hard HEAD^:返回至上一个版本。

Git必须知道当前版本是哪个版本,HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本就是HEAD^^,以此类推上100个需要100个^十分难搞,所以写成HEAD~100

ws@DESKTOP-75BQIUH MINGW64 ~/Desktop/t (master)
$ git reset --hard HEAD^
HEAD is now at f1ed86a father

现在就还原到了第二个版本

我是Ws
我爸是Wjm

此时查看版本历史日志发现回退前的版本快照已经消失了?如果没有快照id我们就不能重返未来了?

解决方法:

1 如果git窗口还在可以向上查找那次commit得到快照id。

2.如果git窗口已关闭则通过git reflog 记录你的每一次命令获取快照。

$ git reflog
f1ed86a (HEAD -> master) HEAD@{0}: reset: moving to HEAD^
1b19a4b HEAD@{1}: commit: mather
f1ed86a (HEAD -> master) HEAD@{2}: reset: moving to HEAD^
236bddb HEAD@{3}: commit: mather
f1ed86a (HEAD -> master) HEAD@{4}: commit: father
3e690b1 HEAD@{5}: commit (initial): add a.txt

回到未来

通过git reflog找到其未来版本的快照id再通过git reset --hard 快照id

$ git reset --hard 236bddb
HEAD is now at 236bddb mather

查看a,果然恢复到了未来的版本。

我是Ws
我爸是Wjm
我妈是Wcl

总结

git reset --hard HEAD^ 返回上一版本

git reset --hard 版本快照id 返回任意指定版本

工作区和版本区

工作区为当前仓库的根目录,隐藏目录.git,这个不算工作区,而是Git的版本库。 还有Git为我们自动创建的第一个默认分支master,以及指向master的一个指针叫HEAD

1.png 前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。 Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。

案例www.liaoxuefeng.com/wiki/896043…

管理修改

因为Git跟踪并管理的是修改,而非文件。

你会问,什么是修改?比如你新增了一行,删除了一行,更改了某些字符,删了一些又加了一些,也是一个修改,甚至创建一个新文件,也算一个修改。

为什么、说Git管理的是修改,而不是文件呢?

$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes.

然后,添加:

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

然后,再修改readme.txt:

$ cat readme.txt 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.

提交:

$ git commit -m "git tracks changes"
[master 519219b] git tracks changes
 1 file changed, 1 insertion(+)

提交后,再看看状态:

$ 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")

仓库状态显示 modified: readme.txt ? 为什么我已经提交了修改但确还显示存没提交修改的文件囊?

看一下过程:第一次修改 -> git add -> 第二次修改 -> git commit 第二次修改没有git add 提交至暂存区所以git commit只提交了第一次修改。 至此可以发现git 管理的是修改而不是文件。

查看工作区和版本库里此文件最新版本的区别

提交后,用git diff HEAD -- readme.txt命令可以查看工作区和版本库里此文件最新版本的区别:

$ git diff HEAD -- readme.txt 
diff --git a/readme.txt b/readme.txt
index 76d770f..a9c5755 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
 Git is a distributed version control system.
 Git is free software distributed under the GPL.
 Git has a mutable index called stage.
-Git tracks changes.
+Git tracks changes of files.

撤销修改

撤销工作区的修改

$ git restore 文件名,撤回工作区的修改; 撤回后$ git status 查看下工作区状态:nothing to commit, working tree cleanb成功

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

撤回暂存区的修改

如果将工作区的修改通过git add . 加入暂存区怎么撤销囊?

git restore --staged <file> :即可撤回暂存区提交的修改,但是工作区的修改依旧存在。可通过git restore 文件名再次撤回工作区修改,至此完成撤回.

撤回版本库的修改

当版本库文件没有推送至远程仓库情况下,可以通过回git reset --hard 版本id退版本达到撤回。

删除文件

当提交a文件至版本库后删除工作区的a文件.

查看状态: Git知道你删除了文件,因此,工作区和版本库就不一致了,git status命令会立刻告诉你哪些文件被删除了,要从版本库中删除该文件,那就用命令git rm删掉,并且git commit提交版本更新。

$ 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:    a.txt

no changes added to commit (use "git add" and/or "git commit -a")
$ git rm a.txt
rm 'a.txt'
$ git commit -m 'rm a.txt'
[master 6d63bde] rm a.txt
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 a.txt

撤销删除

如果在工作区误删a文件,可通过$ git restore 文件名撤销本次修改,在之后使用版本库最新的文件代替,但会丢失删除文件前的修改内容,因为此内容没有commit快照。

github

提供Git仓库托管服务的网站,可提供一个免费的远程仓库。

由于你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,所以,需要一点设置: 如果用户目录下.ssh目录中有id_rsaid_rsa.pub这两个文件则可以跳过。

如果没有则通过如下代码创建SSH Key

创建SSH Key

$ ssh-keygen -t rsa -C "youremail@example.com"

以上操作后一路回车完成后.ssh目录下出现id_rsaid_rsa.pub

id_rsa.pub为公钥;id_rs为私钥。

在gitHub的settings中 找到 ssh and gpg keys 添加公钥, 这下gitHub当前账户下的所有库只认准拥有被添加的公钥用户提交修改。

githubSetting.png

add key.png

在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)

添加远程库

前提条件,你已经在本地创建了一个Git仓库后。又想在GitHub创建一个远程仓库,并且让这两个仓库进行远程同步,这样,GitHub上的仓库既可以作为备份,又可以让其他人通过该仓库来协作,真是一举多得。

gitHub创建库

cku1.png

cku.png

本地库和远程进行关联

$ git remote add origin(默认的远程库名) git@github.com:michaelliao/learngit.git(远程库地址)

删除远程库关联

当本地库关联错远程库,可通过$ git remote rm origin(关联库名)解绑。 仅仅只是解除本地库和绑定库的关系。

当忘记本地库关联的远程库名时可通过$ git remote -v查看。

本地库提交修改至远程库

$ git push -u origin master 其将本地 master分支的改动提交给远程库对应分支,并将本地库当前分支和远程库对应分支相关联,在以后的推送或者拉取时就可以简化命令。

本地库拉取远程库的最新修改

当其他成员上传了最新的修改后如何将本地库进行更新囊? 通过 git pull 库名 被拉取的分支 进行更新。

本地克隆远程库

上次我们讲了先有本地库,后有远程库的时候,再而如何关联远程库。

现在,假设我们从零开发,那么最好的方式是先创建远程库,然后,克隆远程库。

$ git clone git@github.com:michaelliao/gitskills.git