Git
? 再开始这个话题之前, 让我想起了一件很痛苦的事情, 在我大学写毕业论文的时候, 我当时的文件是这样保存的
毕业论文_初稿. doc
毕业论文_修改 1.doc
毕业论文_修改 2.doc
毕业论文_修改 3.doc
毕业论文_完整版 1.doc
毕业论文_完整版 2.doc
毕业论文_完整版 3.doc
毕业论文_死也不改版. doc
毕业论文_最终版 1.doc
毕业论文_最终版 2.doc
? 这个时候, 我们会重复的提交给导师, 导师也会帮我们修改毕业论文, 我自己这里的还好说, 那么如果是导师再给我返回回来的文件, 我就要想想, 我是什么时候提交给导师的, 我要把我后面写的东西跟导师写的东西都添加到我的最新的版本中
以上就是使用最原始的方式进行版本控制, 但是这种方式有显著缺点:
多个文件, 保留所有版本时, 需要为每个版本保存一个文件...
协同操作, 多人协同操作时, 需要将文件打包发来发去...
容易丢失, 被删除意味着永远失去...(可以选择网盘)
? 这个时候我就想, 如果能有一个软件来帮助我来解决这个问题的话, 那是多么好的一件事啊, 这样我自己就不需要去保存所有的文件了, 什么时候需要直接在软件里面看一下, 岂不是很方便.
版本 | 文件名 | 用户 | 说明 | 日期 |
---|---|---|---|---|
1.0 版本 | 毕业论文 | 张三 | 新建 | 2018.1.12 |
1.1 版本 | 毕业论文 | 张三 | 写了第一部分 | 2018.2.12 |
2.0 版本 | 毕业论文 | 张三 | 写完了全部 | 2018.3.23 |
3.0 版本 | 毕业论文 | 张三 | 答辩使用 | 2018.4.25 |
这样你就从版本管理的农耕时代直接进入到了版本控制的 21 世纪, 为了解决以上版本控制存在问题, 应运而生了一批版本控制工具: VSS,CVS,SVN,Git 等, 其中 Git 属于绝对霸主地位.
Git
Git 是一个开源的分布式版本控制软件, 用以有效, 高速的处理从很小到非常大的项目版本管理. Git 最初是由 Linus Torvalds 设计开发的, 用于管理 Linux 内核开发. Git 是根据 GNU 通用公共许可证版本 2 的条款分发的自由 / 免费软件, 安装参见: http://git-scm.com/
GitHub 是一个基于 Git 的远程文件托管平台(同 GitCafe,BitBucket 和 GitLab 等).
Git 本身完全可以做到版本控制, 但其所有内容以及版本记录只能保存在本机, 如果想要将文件内容以及版本记录同时保存在远程, 则需要结合 GitHub 来使用. 使用场景:
无 GitHub: 在本地 .Git 文件夹内维护历时文件
有 GitHub: 在本地 .Git 文件夹内维护历时文件, 同时也将历时文件托管在远程仓库
其他:
? 集中式: 远程服务器保存所有版本, 用户客户端有某个版本
? 分布式: 远程服务器保存所有版本, 用户客户端有所有版本
安装
在 Linux 上安装
如果你想在 Linux 上用二进制安装程序来安装 Git, 可以使用发行版包含的基础软件包管理工具来安装. 如果以 Fedora 上为例, 你可以使用 yum:
$ sudo yum install Git
如果你在基于 Debian 的发行版上, 请尝试用 apt-get:
$ sudo apt-get install Git
在 Mac 上安装
在 Mac 上安装 Git 有多种方式. 最简单的方法是安装 Xcode Command Line Tools. Mavericks (10.9) 或更高版本的系统中, 在 Terminal 里尝试首次运行 Git 命令即可. 如果没有安装过命令行开发者工具, 将会提示你安装.
如果你想安装更新的版本, 可以使用二进制安装程序. 官方维护的 OS X Git 安装程序可以在 Git 官方网站下载, 网址为 <http://git-scm.com/download/mac> http://git-scm.com/download/mac%3E ;.
在 Windows 上安装
在 Windows 上安装 Git 也有几种安装方法. 官方版本可以在 Git 官方网站下载. 打开 <http://git-scm.com/download/win>, 下载会自动开始. 要注意这是一个名为 Git for Windows 的项目(也叫做 msysGit), 和 Git 是分别独立的项目; 更多信息请访问 <http://msysgit.github.io/> http://msysgit.github.io/%3E ;.
另一个简单的方法是安装 GitHub for Windows. 该安装程序包含图形化和命令行版本的 Git. 它也能支持 Powershell, 提供了稳定的凭证缓存和健全的 CRLF 设置. 稍后我们会对这方面有更多了解, 现在只要一句话就够了, 这些都是你所需要的. 你可以在 GitHub for Windows 网站下载, 网址为 http://windows.github.com/ http://windows.github.com/ .
命令行
Git 有多种使用方式. 你可以使用原生的命令行模式, 也可以使用 GUI 模式, 这些 GUI 软件也能提供多种功能. 在本书中, 我们将使用命令行模式. 这是因为首先, 只有在命令行模式下你才能执行 Git 的 所有命令, 而大多数的 GUI 软件只实现了 Git 所有功能的一个子集以降低操作难度. 如果你学会了在命令行下如何操作, 那么你在操作 GUI 软件时应该也不会遇到什么困难, 但是, 反之则不成立. 此外, 由于每个人的想法与侧重点不同, 不同的人常常会安装不同的 GUI 软件, 但 所有 人一定会有命令行工具.
假如你是 Mac 用户, 我们希望你懂得如何使用终端 (Terminal); 假如你是 Windows 用户, 我们希望你懂得如何使用命令窗口(Command Prompt) 或 PowerShell. 如果你尚未掌握以上技能, 我们建议你先停下来快速学习一下, 本书中的讲述和举例将用到这些技能.
Git 基础
获取 Git 仓库
在现有目录中初始化仓库
如果你打算使用 Git 来对现有的项目进行管理, 你只需要进入该项目目录并输入:
[Derek@Git]$ Git init
该命令将创建一个名为 .Git 的子目录, 这个子目录含有你初始化的 Git 仓库中所有的必须文件. 但是, 在这个时候, 我们仅仅是做了一个初始化的操作, 你的项目里的文件还没有被跟踪.
那么怎么来实现项目中的管理那?
和把大象放到冰箱需要 3 步相比, 把一个文件放到 Git 仓库只需要两步.
第一步, 用命令 Git add 告诉 Git, 把文件添加到仓库:
[Derek@Git]$ Git add readme.txt
执行上面的命令, 没有任何显示, 这就对了, Unix 的哲学是 "没有消息就是好消息", 说明添加成功.
第二步, 用命令 Git commit 告诉 Git, 把文件提交到仓库:
- [Derek@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
简单解释一下 Git commit 命令,-m 后面输入的是本次提交的说明, 可以输入任意内容, 当然最好是有意义的, 这样你就能从历史记录里方便地找到改动记录.
嫌麻烦不想输入 - m "xxx" 行不行? 确实有办法可以这么干, 但是强烈不建议你这么干, 因为输入说明对自己对别人阅读都很重要. 实在不想输入说明的童鞋请自行 Google, 我不告诉你这个参数.
Git commit 命令执行成功后会告诉你, 1 file changed:1 个文件被改动(我们新添加的 readme.txt 文件);2 insertions: 插入了两行内容(readme.txt 有两行内容).
记录每次更新到仓库
我们已经成功地添加并提交了一个 readme.txt 文件, 现在, 是时候继续工作了, 于是, 我们继续修改 readme.txt 文件, 改成如下内容:
- Git is a distributed version control system.
- Git is free software.
现在, 运行 Git status 命令看看结果:
- [Derek@Git]$ 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 status 命令的输出对于你来说过于模糊, 你想知道具体修改了什么地方, 可以用 Git diff 命令. 稍后我们会详细介绍 Git diff, 你可能通常会用它来回答这两个问题: 当前做的哪些更新还没有暂存? 有哪些更新已经暂存起来准备好了下次提交? 尽管 Git status 已经通过在相应栏下列出文件名的方式回答了这个问题, Git diff 将通过文件补丁的格式显示具体哪些行发生了改变.
- [Derek@Git]$ Git diff
- diff --Git a/README.md b/README.md
- index e69de29..a34691f 100644
- --- a/README.md
- +++ b/README.md
- @@ -0,0 +1 @@
- +this is new line
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异, 也就是修改之后还没有暂存起来的变化内容.
若要查看已暂存的将要添加到下次提交里的内容, 可以用 Git diff --cached 命令.(Git 1.6.1 及更高版本还允许使用 Git diff --staged, 效果是相同的, 但更好记些.)
- [Derek@Git]$ Git diff --staged
- diff --Git a/README.md b/README.md
- new file mode 100644
- index 0000000..e69de29
提交更新
现在的暂存区域已经准备妥当可以提交了. 在此之前, 请一定要确认还有什么修改过的或新建的文件还没有 Git add 过, 否则提交的时候不会记录这些还没暂存起来的变化. 这些修改过的文件只保留在本地磁盘. 所以, 每次准备提交前, 先用 Git status 看下, 是不是都已暂存起来了, 然后再运行提交命令 Git commit:
[Derek@Git]$ Git commit
-m 选项, 将提交信息与命令放在同一行
- [Derek@Git]$ Git commit -m 'create'
- [master (root-commit) 88a09aa] create
- 1 file changed, 0 insertions(+), 0 deletions(-)
- create mode 100644 README.md
跳过使用暂存区域
尽管使用暂存区域的方式可以精心准备要提交的细节, 但有时候这么做略显繁琐. Git 提供了一个跳过使用暂存区域的方式, 只要在提交的时候, 给 Git commit 加上 -a 选项, Git 就会自动把所有已经跟踪过的文件暂存起来一并提交
- [Derek@Git]Git commit -a -m 'update'
- [master 86d801b] update
- 1 file changed, 1 insertion(+)
查看提交历史
- [Derek@Git]$ Git log
- commit 86d801bbaa4cc560acc7c8f79a65cac85201f170 (HEAD -> master)
- Author: wangfeng7399 <wangfeng17399@163.com>
- Date: Tue Feb 19 18:48:48 2019 +0800
- update
- commit 88a09aa009af29e9a784d6dbb68589f70f1c51be
- Author: wangfeng7399 <wangfeng17399@163.com>
- Date: Tue Feb 19 18:48:04 2019 +0800
- create
-p 用来显示每次提交的内容差异
你也可以加上 -2 来仅显示最近两次提交
- [Derek@Git]Git log -p -2
- commit 86d801bbaa4cc560acc7c8f79a65cac85201f170 (HEAD -> master)
- Author: wangfeng7399 <wangfeng17399@163.com>
- Date: Tue Feb 19 18:48:48 2019 +0800
- update
- diff --Git a/README.md b/README.md
- index e69de29..a34691f 100644
- --- a/README.md
- +++ b/README.md
- @@ -0,0 +1 @@
- +this is new line
- commit 88a09aa009af29e9a784d6dbb68589f70f1c51be
- Author: wangfeng7399 <wangfeng17399@163.com>
- Date: Tue Feb 19 18:48:04 2019 +0800
- create
- diff --Git a/README.md b/README.md
- new file mode 100644
- index 0000000..e69de29
另外一个常用的选项是 --pretty. 这个选项可以指定使用不同于默认格式的方式展示提交历史. 这个选项有一些内建的子选项供你使用. 比如用 oneline 将每个提交放在一行显示, 查看的提交数很大时非常有用. 另外还有 short,full 和 fuller 可以用, 展示的信息或多或少有些不同, 请自己动手实践一下看看效果如何.
- [Derek@Git]$ Git log --pretty=oneline
- ca82a6dff817ec66f44342007202690a93763949 changed the version number
- 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
- a11bef06a3f659402fe7563abf99ad00de2209e6 first commit
但最有意思的是 format, 可以定制要显示的记录格式. 这样的输出对后期提取分析格外有用?-? 因为你知道输出的格式不会随着 Git 的更新而发生改变:
Git log --pretty=format 常用的选项 https://git-scm.com/book/zh/v2/ch00/rpretty_format 列出了常用的格式占位符写法及其代表的意义.
选项 | 说明 |
---|---|
%H | 提交对象(commit)的完整哈希字串 |
%h | 提交对象的简短哈希字串 |
%T | 树对象(tree)的完整哈希字串 |
%t | 树对象的简短哈希字串 |
%P | 父对象(parent)的完整哈希字串 |
%p | 父对象的简短哈希字串 |
%an | 作者(author)的名字 |
%ae | 作者的电子邮件地址 |
%ad | 作者修订日期(可以用 --date= 选项定制格式) |
%ar | 作者修订日期,按多久以前的方式显示 |
%cn | 提交者(committer)的名字 |
%ce | 提交者的电子邮件地址 |
%cd | 提交日期 |
%cr | 提交日期,按多久以前的方式显示 |
%s | 提交说明 |
Git log 的常用选项
选项 | 说明 |
---|---|
-p | 按补丁格式显示每个更新之间的差异。 |
--stat | 显示每次更新的文件修改统计信息。 |
--shortstat | 只显示 --stat 中最后的行数修改添加移除统计。 |
--name-only | 仅在提交信息后显示已修改的文件清单。 |
--name-status | 显示新增、修改、删除的文件清单。 |
--abbrev-commit | 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。 |
--relative-date | 使用较短的相对时间显示(比如,“2 weeks ago”)。 |
--graph | 显示 ASCII 图形表示的分支合并历史。 |
--pretty | 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。 |
在 限制 Git log 输出的选项 https://git-scm.com/book/zh/v2/ch00/rlimit_options 中列出了常用的选项
选项 | 说明 |
---|---|
-(n) | 仅显示最近的 n 条提交 |
--since, --after | 仅显示指定时间之后的提交。 |
--until, --before | 仅显示指定时间之前的提交。 |
--author | 仅显示指定作者相关的提交。 |
--committer | 仅显示指定提交者相关的提交。 |
--grep | 仅显示含指定关键字的提交 |
-S | 仅显示添加或移除了某个关键字的提交 |
取消暂存的文件
例如, 你已经修改了两个文件并且想要将它们作为两次独立的修改提交, 但是却意外地输入了 Git add * 暂存了它们两个. 如何只取消暂存两个中的一个呢? Git status 命令提示了你:
- [Derek@Git]Git status
- On branch master
- Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
- modified: README.md
- [Derek@Git]Git reset HEAD README.md
- Unstaged changes after reset:
- M README.md
- [Derek@Git]$ 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.md
- no changes added to commit (use "git add" and/or "git commit -a")
虽然在调用时加上 --hard 选项可以令 Git reset 成为一个危险的命令, 可能导致工作目录中所有当前进度丢失! 但本例中工作目录内的文件并不会被修改. 不加选项地调用 Git reset 并不危险 它只会修改暂存区域.
撤消对文件的修改
如果你并不想保留对 README.md 文件的修改怎么办? 你该如何方便地撤消修改 - 将它还原成上次提交时的样子(或者刚克隆完的样子, 或者刚把它放入工作目录时的样子)? 幸运的是, 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.md
它非常清楚地告诉了你如何撤消之前所做的修改. 让我们来按照提示执行:
- $ Git checkout -- README.md
- $ Git status
- On branch master
- Changes to be committed:
- (use "git reset HEAD <file>..." to unstage)
- renamed: README.md -> README
可以看到那些修改已经被撤消了.
你需要知道 Git checkout -- [file] 是一个危险的命令, 这很重要. 你对那个文件做的任何修改都会消失 - 你只是拷贝了另一个文件来覆盖它. 除非你确实清楚不想要那个文件了, 否则不要使用这个命令.
来源: http://www.bubuko.com/infodetail-2962546.html