Git安装、配置和使用(下)

简介: Git安装、配置和使用(下)

提交变动到仓库


第二步,用命令git commit告诉 Git,把文件提交到仓库:


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


80efc0efa74d4396ab359a05600d3dfa.png


这里简单解释一下git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。


git commit命令执行成功后会告诉你:


1 file changed:1个文件被改动(我们新添加的readme.txt文件)

2 insertions:插入了两行内容(readme.txt有两行内容)


为什么 Git 添加文件需要add,commit一共两步呢?因为commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:


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


查看Git仓库当前状态变化


我们已经成功地添加并提交了一个readme.txt文件,接下来让我们继续修改readme.txt文件,改成如下内容:


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


查看 git status 结果


现在,运行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 告诉我们readme.txt被修改了,但并没有告诉我们具体修改的内容是什么,假如刚好是上周修改的,等到周一来班时,已经记不清上次怎么修改的readme.txt,这个时候我们就需要用git diff这个命令查看相较于上一次暂存都修改了些什么内容了:


运行 git diff 命令


$ git diff readme.txt 
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 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.
 (END)


git diff顾名思义就是查看 difference,显示的格式正是 Unix 通用的 diff 格式,可以从上面的输出看到,我们在第一行添加了一个distributed单词。


综合操作


知道了对readme.txt作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是git add


git add


$ git add readme.txt


同样没有任何输出。在执行第二步git commit之前,我们再运行git status看看当前仓库的状态:


git status


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


git status告诉我们,将要被提交的修改包括readme.txt,下一步,就可以放心地提交了:


** git commit**


$ git commit -m "add distributed"
[master e55063a] add distributed
 1 file changed, 1 insertion(+), 1 deletion(-)


提交后,我们再用git status命令看看仓库的当前状态:


** git status**

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


Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的。


查看日志


如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:


** git log --pretty=oneline**


$ git log --pretty=oneline
e55063ad7f97dd979e4f94e12d2bc44a25a0fd55 (HEAD -> master) add distributed
50ed06bd62fd34afbe501e6f2a4af73ccbe187f0 wrote a readme file
(END)


每提交一个新版本,实际上 Git 就会把它们自动串成一条时间线。如果使用可视化工具或者之前在 git 自定义配置中介绍的 git lg命令,就可以更清楚地看到提交历史的时间线:


$ git lg
* e55063a - (HEAD -> master) add distributed (4 minutes ago) <Miykael_xxm>
* 50ed06b - wrote a readme file (6 minutes ago) <Miykael_xxm>
(END)


作为一个优秀的版本控制系统,Git 能够让我们查看每一次提交的记录。在日常的工作中,我们可以随时对 Git 仓库中的内容进行修改,,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在 Git中 被称为commit / 提交。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit恢复,然后继续工作,而不是把几个月的工作成果全部丢失。


** git log**


在 Git 中,我们可以通过git log命令查看全部的commit记录:


$ git log
commit e55063ad7f97dd979e4f94e12d2bc44a25a0fd55 (HEAD -> master)
Author: Miykael_xxm <xiongjiamu@gmail.com>
Date:   Fri Nov 27 16:08:04 2020 +0800
    add distributed
commit 50ed06bd62fd34afbe501e6f2a4af73ccbe187f0
Author: Miykael_xxm <xiongjiamu@gmail.com>
Date:   Fri Nov 27 16:06:11 2020 +0800
    wrote a readme file
(END)


git log命令显示从最近到最远的提交日志,我们可以看到2次提交,最近的一次是add distributed,最早的一次是wrote a readme file


Git 回退


这个时候,假设我们需要将 readme.txt 回退到上一个版本,也就是 wrote a readme file 的这个版本,我们需要怎么操作呢?


首先,Git 必须知道当前版本是哪个版本,在 Git 中,用HEAD表示当前版本,也就是最新的提交e55063a,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。


现在,我们要把当前版本add distributed回退到上一个版本wrote a readme file,就可以使用git reset命令:


** git reset**


$ git reset --hard HEAD^
HEAD is now at 50ed06b wrote a readme file


现在让我们看看readme.txt的内容是不是版本wrote a readme file:


1. $ cat readme.txt
2. Git is a version control system.
3. Git is free software.


果然还原到最初wrote a readme file这个版本了。


Git 的版本回退速度非常快,因为 Git 在内部有个指向当前版本的HEAD指针,当你回退版本的时候,Git 仅仅是把HEAD从指向add distributed:


** HEAD 指针移动记录**


┌────┐
│HEAD│
└────┘
   └──> ○ add distributed
        ○ wrote a readme file


改为指向wrote a readme file:


┌────┐
│HEAD│
└────┘
   │    ○ add distributed
   │    │
   └──> ○ wrote a readme file


然后顺便把工作区的文件更新了。所以你让HEAD指向哪个版本号,你就把当前版本定位在哪。


Git重置


现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id怎么办?


好在 Git 提供了一个命令git reflog用来记录你的每一次命令,当你用git reset --hard HEAD^回退到wrote a readme file版本时,再想恢复到add distributed,就可以通过git reflog命令找到add distributed的commit id。


** git reflog**


$ git reflog
50ed06b (HEAD -> master) HEAD@{0}: reset: moving to HEAD~
e55063a HEAD@{1}: reset: moving to HEAD
e55063a HEAD@{2}: commit: add distributed
50ed06b (HEAD -> master) HEAD@{3}: commit (initial): wrote a readme file
ESC


从上面的输出可以看到,add distributedcommit ide55063a,现在,我们就可以通过 git reset --hard e55063a切换到最新的版本上了。


工作区和暂存区


Git 和其他版本控制系统如 SVN 的一个不同之处就是有暂存区的概念。


工作区(Working Directory)


就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区:


版本库(Repository)


工作区有一个隐藏目录.git,这个不算工作区,而是 Git 的版本库。


Git 的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有 Git 为我们自动创建的第一个分支master,以及指向 master 的一个指针叫HEAD。


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


第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;

第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

因为我们创建 Git 版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往 master 分支上提交更改。


你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。


现在,我们来试一下,先对readme.txt做个修改,比如加上一行内容:


Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.


然后,在工作区新增一个LICENSE文本文件。


先用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")


Git非常清楚地告诉我们,readme.txt被修改了,而LICENSE还从来没有被添加过,所以它的状态是Untracked。


现在,使用两次命令git add,把readme.txt和LICENSE都添加后,用git status再查看一下:


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


现在,暂存区的状态就变成这样了.


所以,git add命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit就可以一次性把暂存区的所有修改提交到分支。


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


一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:


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


现在版本库变成了这样,暂存区就没有任何内容了


五、版本管理


撤消修改(git commit --amend)


在任何一个阶段,你都有可能想要撤消某些操作。接下来,我们将会学习几个撤消你所做修改的基本命令。 注意,有些撤消操作是不可逆的。 这是在使用 Git 的过程中,会因为操作失误而导致之前的工作丢失的少有的几个地方之一。


有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令来重新提交:


git commit --amend


1. $ git commit --amend
2.


这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。


文本编辑器启动后,可以看到之前的提交信息。 编辑后保存会覆盖原来的提交信息。


例如,你提交后发现忘记了暂存某些需要的修改,可以像下面这样操作:


$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend


最终你只会有一个提交——第二次提交将代替第一次提交的结果。


当你在修补最后的提交时,并不是通过用改进后的提交 原位替换 掉旧有提交的方式来修复的, 理解这一点非常重要。从效果上来说,就像是旧有的提交从未存在过一样,它并不会出现在仓库的历史中。


修补提交最明显的价值是可以稍微改进你最后的提交,而不会让“啊,忘了添加一个文件”或者 “小修补,修正笔误”这种提交信息弄乱你的仓库历史。


取消暂存的文件(git reset)


接下来我们看看如何操作暂存区和工作目录中已修改的文件。 这些命令在修改文件状态的同时,也会提示如何撤消操作。例如,你已经修改了两个文件并且想要将它们作为两次独立的修改提交, 但是却意外地输入 git add * 暂存了它们两个。如何只取消暂存两个中的一个呢? git status 命令提示了你:


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


在 “Changes to be committed” 文字正下方,提示使用 git reset HEAD <file>... 来取消暂存。 所以,我们可以这样来取消暂存 readme.txt 文件:


git reset HEAD


$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
    renamed:    LICENSE -> LICENSE.md
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


这个命令有点儿奇怪,但是起作用了。 readme.txt 文件已经是修改未暂存的状态了。


git reset 确实是个危险的命令,如果加上了 --hard 选项则更是如此。 然而在上述场景中,工作目录中的文件尚未修改,因此相对安全一些。


撤消对文件的修改(git --checkout)


如果你并不想保留对 readme.txt 文件的修改怎么办? 你该如何方便地撤消修改——将它还原成上次提交时的样子(或者刚克隆完的样子,或者刚把它放入工作目录时的样子)? 幸运的是,git status 也告诉了你应该如何做。 在最后一个例子中,未暂存区域是这样:


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


它非常清楚地告诉了你如何撤消之前所做的修改。 让我们来按照提示执行:


git checkout – file


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


可以看到那些修改已经被撤消了。


请务必记得 git checkout -- <file> 是一个危险的命令。 你对那个文件在本地的任何修改都会消失——Git 会用最近提交的版本覆盖掉它。 除非你确实清楚不想要对那个文件的本地修改了,否则请不要使用这个命令。


删除文件


Git 中,删除也是一个修改操作,我们先添加一个新文件test.txtGit 并且提交:


$ git add test.txt
$ git commit -m "add test.txt"
[master c67077f] add test.txt
 1 file changed, 1 insertion(+)
 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 restore <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 5c7e5ea] remove test.txt
 1 file changed, 1 deletion(-)
 delete mode 100644 test.txt


现在,文件就从版本库中被删除了。


小提示:先手动删除文件,然后使用git rmgit add效果是一样的。


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


$ git checkout -- test.txt


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


注意:从来没有被添加到版本库就被删除的文件,是无法恢复的!


小结


好了,以上这些就是 git 中关于撤销以及删除文件的相关内容了,让我们来回顾一下:


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

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

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,可以用命令git reset --hard commit_id,不过前提是没有推送到远程库。


六、分支管理


前面我们了解到,Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照 。


在进行提交操作时,Git  会保存一个提交对象(commit object)。 知道了 Git 保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。 但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。 首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象, 而由多个分支合并产生的提交对象有多个父对象,


为了更加形象地说明,我们假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件。 暂存操作会为每一个文件计算校验和,然后会把当前版本的文件快照保存到 Git  仓库中 (Git 使用 blob 对象来保存它们),最终将校验和加入到暂存区域等待提交:


$ git add readme.txt test.md LICENSE
$ git commit -m 'The initial commit of my project'


当使用 git commit 进行提交操作时,Git  会先计算每一个子目录(本例中只有项目根目录)的校验和, 然后在 Git 仓库中这些校验和保存为树对象。随后,Git  便会创建一个提交对象, 它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。 如此一来,Git 就可以在需要的时候重现此次保存的快照。


现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个 树 对象 (记录着目录结构和 blob 对象索引)以及一个 提交 对象(包含着指向前述树对象的指针和所有提交信息)。


这里用到再说,有点复杂。


七、Git标签


Git 的标签虽然是版本库的快照,但其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。


tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。


创建标签


Git 中创建标签非常简单,首先,切换到需要打标签的分支上:


$ git branch
* dev
  master
$ git checkout master
Switched to branch 'master'

然后,敲命令git tag <name>就可以打一个新标签:


$ git tag v1.0

可以用命令git tag查看所有标签:


1. $ git tag
2. v1.0


默认标签是打在最新提交的commit上的。有时候,如果忘了打标签,比如,现在已经是周五了,但应该在周一打的标签没有打,怎么办?


方法是找到历史提交的commit id,然后打上就可以了:


$ git log --pretty=oneline --abbrev-commit
5c7e5ea (HEAD -> master) remove test.txt
c67077f add test.txt
fb8b190 conflict fixed
06e5e3a & simple
2443c95 add simple
4aac6c7 branch test
599dbdb understand how stage works
1985ccf append GPL
27f9df6 add distributed
e372504 wrote a readme file


比方说要对conflict fixed这次提交打标签,它对应的commit idfb8b190,敲入命令:


$ git tag v0.9 fb8b190

再用命令git tag查看标签:


1. $ git tag
2. v0.9
3. v1.0


注意,标签不是按时间顺序列出,而是按字母排序的。可以用git show 查看标签信息:


$ git show v0.9
commit fb8b1903706eeaa8141894f1af859f0dfee3e0d9 (tag: v0.9)
Merge: 06e5e3a 2443c95
Author: Miykael_xxm <xiongjiamu@gmail.com>
Date:   Sun Nov 29 20:18:26 2020 +0800
    conflict fixed
(END)


可以看到,v0.9确实打在conflict fixed这次提交上。


还可以创建带有说明的标签,用-a指定标签名,-m指定说明文字:


$ git tag -a v0.1 -m "version 0.1 released" 1985ccf


用命令git show <tagname>可以看到说明文字:


$ git show v0.1
tag v0.1
Tagger: Miykael_xxm <xiongjiamu@gmail.com>
Date:   Sun Nov 29 22:06:05 2020 +0800
version 0.1 released
commit 1985ccf5b6710edf3bcd7c0700e6d96cab335e61 (tag: v0.1, tag: remove)
Author: Miykael_xxm <xiongjiamu@gmail.com>
Date:   Fri Nov 27 16:14:27 2020 +0800
    append GPL
diff --git a/readme.txt b/readme.txt
index 9247db6..8443d23 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
 Git is a distributed version control system.
-Git is free software.
+Git is free software distributed under the GPL.
(END)


注意:标签总是和某个commit挂钩。如果这个commit既出现在master分支,又出现在dev分支,那么在这两个分支上都可以看到这个标签。


标签操作


如果标签打错了,也可以删除:


$ git tag -d v0.1
Deleted tag 'v0.1' (was 3be0bf5)


因为创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除。


如果要推送某个标签到远程,使用命令git push origin <tagname>:


$ git push origin v1.0
Total 0 (delta 0), reused 0 (delta 0), pack-reused 0
To codechina.csdn.net:xiongjiamu/learing.git
 * [new tag]         v1.0 -> v1.0


或者,一次性推送全部尚未推送到远程的本地标签:


$ git push origin --tags
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 170 bytes | 170.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
To codechina.csdn.net:xiongjiamu/learing.git
 * [new tag]         remove -> remove
 * [new tag]         v0.1 -> v0.1
 * [new tag]         v0.9 -> v0.9


如果标签已经推送到远程,要删除远程标签就麻烦一点,先从本地删除:


1. $ git tag -d remove
2. Deleted tag 'remove' (was 1985ccf)


然后,从远程删除。删除命令也是push,但是格式如下:


$ git push origin :refs/tags/remove
To codechina.csdn.net:xiongjiamu/learing.git
 - [deleted]         remove


要看看是否真的从远程库删除了标签,可以登录 CODE CHINA 上查看。


小结


以上就是 git tag操作的内容介绍了,现在让我们来回顾一下:


命令git push origin <tagname>可以推送一个本地标签;

命令git push origin --tags可以推送全部未推送过的本地标签;

命令git tag -d <tagname>可以删除一个本地标签;

命令git push origin :refs/tags/<tagname>可以删除一个远程标签

命令git tag -a <tagname> -m 'messages'可以创建一个带附注的标签

命令git tag -s <tagname> -m 'messages'可以创建一个带 gpg 签名的标签

参考:http://t.csdn.cn/Ls97m

目录
相关文章
|
2月前
|
安全 Shell 网络安全
【Git】TortoiseGit(小乌龟)配置SSH和使用
【Git】TortoiseGit(小乌龟)配置SSH和使用
152 0
|
1月前
|
开发工具 数据库 数据安全/隐私保护
【Git】—— git的配置
【Git】—— git的配置
【Git】—— git的配置
|
1月前
|
存储 JavaScript 开发工具
Windows 10环境下Git安装之简易指南
该指南教小白在Windows 10上安装Git,介绍Git设置的基础知识,为你的开发项目做准备!
|
2月前
|
网络安全 开发工具 数据安全/隐私保护
[Git]关联远程库的两种方法及配置
本篇文章对gitee公钥配置、同电脑连接多个gitee账号公钥配置等方法进行阐述, 如果文中阐述不全或不对的,多多交流。
72 0
[Git]关联远程库的两种方法及配置
|
3月前
|
Linux Shell 开发工具
git的安装
git的安装
39 0
|
3月前
|
存储 网络安全 数据处理
git远程操作,推送【push】,拉取【pull】,忽略特殊文件,配置别名,标签管理
git远程操作,推送【push】,拉取【pull】,忽略特殊文件,配置别名,标签管理
|
4月前
|
Ubuntu Linux 开发工具
Linux Ubuntu配置Git的方法
Linux Ubuntu配置Git的方法
|
4月前
|
编译器 定位技术 开发工具
分布式版本控制系统Git的下载、安装与使用其复制GitHub项目代码的方法
分布式版本控制系统Git的下载、安装与使用其复制GitHub项目代码的方法
|
4月前
|
Linux Shell 开发工具
配置git识别中文
配置git识别中文
39 1
|
4月前
|
Shell 网络安全 开发工具
Git下载安装及基本配置
Git下载安装及基本配置
106 0