Skip to content
This repository has been archived by the owner on Sep 10, 2019. It is now read-only.

更新 2.3 保存你的更改(修复图片) #79

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 11 additions & 141 deletions sources/2.3-保存你的更改.md
Original file line number Diff line number Diff line change
@@ -1,158 +1,28 @@

# 保存你的更改

![Saving changes](https://wac-cdn.atlassian.com/dam/jcr:75f75cb6-a6ab-4f0b-ab29-e366914f513c/hero.svg?cdnVersion=kg)

***git add / git commit / git diff / git stash / .gitignore***
***[git add](2.3.1-git_add.md) / [git commit](2.3.2-git_commit.md) / [git diff](2.3.3-git_diff.md) / [git stash](2.3.4-git_stash.md) / [.gitignore](2.3.5-git_ignore.md)***

> ✍️ [童仲毅](https://github.com/geeeeeeeeek) | ⏳ 2018 年 1026 日(部分章节未更新)
> ✍️ [童仲毅](https://github.com/geeeeeeeeek) | ⏳ 2018 年 121 日
>
> ©️ 本文演绎自 Atlassian 编写的 [_Saving Changes_](https://www.atlassian.com/git/tutorials/saving-changes)。页面上所有内容采用知识共享-署名([CC BY 2.5 AU](http://creativecommons.org/licenses/by/2.5/au/deed.zh))许可协议。

“保存”这个概念在 Git 等版本控制系统和 Word 等文本编辑应用中不太一样。传统软件里的“保存”在 Git 里被叫做“提交”(commit)。 我们常说的的保存可以理解成在文件系统中覆盖一个已有的文件或者创建一个新的文件。而在 Git 中,提交这个操作作用于若干个文件和目录。

在 Git 和 SVN 里保存更改也不一样。SVN 提交或检入(check-in)将会推送到远端的中央服务器。也就是说 SVN 的提交需要联网才能完全“保存”项目更改。Git 提交可以在本地完成,然后再使用`git push -u origin master`命令推送到远端服务器。这两种方法的区别体现了两种架构设计的本质区别。Git 是一个分布式的应用,而 SVN 是一个中心化的应用。分布式应用一般来说更可靠,因为它们不存在中央服务器这样的单点故障。

`git add`、`git status`和`git commit`这三个命令通常一起使用,将 Git 项目当前的状态保存成一份快照。

Git 还有另一个保存机制:“储藏”(stash)。储藏是一个临时的储存区域,保存还没准备好提交的更改。储藏操作作用于工作目录,三个文件树中的第一棵。它有很多用法,访问 git stash 页面了解更多。

Git 仓库可以通过设置忽略一些文件或目录。Git 将不会保存这些文件的任何更改。Git 有多种方式管理忽略文件列表。访问 git ignore 页面了解更多 Git 忽略文件设置。

## git add

`git add` 命令将工作目录中的变化添加到暂存区。它告诉 Git 你想要在下一次提交时包含这个文件的更新。但是,`git add` 不会实质上地影响你的仓库——在你运行 `git commit` 前更改都还没有真正被记录。

使用这些命令的同时,你还需要 `git status` 来查看工作目录和暂存区的状态。

### 用法

```
git add <file>
```

将 `<file>` 中的更改加入下次提交的缓存。

```
git add <directory>
```

将 `<directory>` 下的更改加入下次提交的缓存。

```
git add -i
```

开始交互式的缓存,你可以选择文件的一部分加入到下次提交缓存。它会向你展示一堆更改,等待你输入一个命令。`y` 将这块更改加入缓存,`n` 忽略这块更改,`s` 将它分割成更小的块,`e` 手动编辑这块更改,以及 `q` 退出。

### 讨论

`git add` 和 `git commit` 这两个命令组成了最基本的 Git 工作流。每一个 Git 用户都需要理解这两个命令,不管他们团队的协作模型是如何的。我有一千种方式可以将项目版本记录在仓库的历史中。

在一个只有编辑、缓存、提交这样基本流程的项目上开发。首先,你要在工作目录中编辑你的文件。当你准备备份项目的当前状态时,你通过 `git add` 来缓存更改。当你对缓存的快照满意之后,你通过 `git commit` 将它提交到你的项目历史中去。

![Git Tutorial: git add Snapshot](https://wac-cdn.atlassian.com/dam/jcr:0f27e004-f2f5-4890-921d-65fa77ba2774/01.svg)

`git add` 命令不能和 `svn add` 混在一起理解,后者将文件添加到仓库中。而 `git add` 发生于更抽象的 *更改* 层面。也就是说,`git add` 在每次你修改一个文件时都需要被调用,而 `svn add` 只需要每个文件调用一次。这听上去很多余,但这样的工作流使得一个项目更容易组织。

#### 缓存区

缓存区是 Git 更为独特的地方之一,如果你是从 SVN(甚至是 Mercurial)迁移而来,那你可得花点时间理解了。你可以简单地把它想成是工作目录和项目历史之间的缓冲区。

缓存允许你在实际提交到项目历史之前,将相关的更改组合成一份高度专注的快照,而不是将你上次提交以后产生的所有更改一并提交。也就是说你可以更改各种不相关的文件,然后回过去将它们按逻辑切分,将相关的更改添加到缓存,一份一份提交。在任何修改控制系统中,很重要的一点是提交必须是原子性的,以便于追踪 bug,并用最小的代价回滚更改。

### 栗子

当你开始新项目的时候,`git add` 和 `svn import` 类似。为了创建当前目录的初始提交,使用下面两个命令:

```
git add .
git commit
```

当你项目设置好之后,新的文件可以通过路径传递给 `git add` 来添加:

```
git add hello.py
git commit
```

上面的命令同样可以用于记录已有文件的更改。重复一次,Git 不会区分缓存的更改来自新文件,还是仓库中已有的文件。

## git commit

`git commit`命令将缓存的快照提交到项目历史。提交的快照可以认为是项目安全的版本,Git 永远不会改变它们,除非你这么要求。和 `git add` 一样,这是最重要的 Git 命令之一。

尽管和它和 `svn commit` 名字一样,但实际上它们毫无关联。快照被提交到本地仓库,不会和其他 Git 仓库有任何交互。

### 用法

```
git commit
```

提交已经缓存的快照。它会运行文本编辑器,等待你输入提交信息。当你输入信息之后,保存文件,关闭编辑器,创建实际的提交。

```
git commit -m "<message>"
```

提交已经缓存的快照。但将 `<message>` 作为提交信息,而不是运行文本编辑器。

```
git commit -a
```

提交一份包含工作目录所有更改的快照。它只包含跟踪过的文件的更改(那些之前已经通过 `git add` 添加过的文件)。

### 讨论

快照总是提交到 *本地* 仓库。这一点和 SVN 截然不同,后者的工作拷贝提交到中央仓库。而 Git 不会强制你和中央仓库进行交互,直到你准备好了。就像缓存区是工作目录和项目历史之间的缓冲地带,每个开发者的本地仓库是他们贡献的代码和中央仓库之间的缓冲地带。

这一点改变了 Git 用户基本的开发模型。Git 开发者可以在本地仓库中积累一些提交,而不是一发生更改就直接提交到中央仓库。这对于 SVN 风格的协作有着诸多优点:更容易将功能切分成原子性的提交,让相关的提交组合在一起,发布到中央仓库之前整理好本地的历史。开发者得以在一个隔离的环境中工作,直到他们方便的时候再整合代码。

#### 记录快照,而不是记录差异

SVN 和 Git 除了使用上存在巨大差异,它们底层的实现同样遵循截然不同的设计哲学。SVN 追踪文件的 *变化* ,而 Git 的版本控制模型基于 *快照* 。比如说,一个 SVN 提交由仓库中原文件相比的差异(diff)组成。而 Git 在每次提交中记录文件的 *完整内容* 。

![Git Tutorial: Snapshots, Not Differences](https://www.atlassian.com/dam/jcr:7406fe56-d36d-44cf-92e3-b28e4bae36f8/02.svg)

这让很多 Git 操作比 SVN 来的快得多,因为文件的某个版本不需要通过版本间的差异组装得到——每个文件完整的修改能立刻从 Git 的内部数据库中得到。

Git 的快照模型对它版本控制模型的方方面面都有着深远的影响,从分支到合并工具,再到协作工作流,以至于影响了所有特性。

### 栗子

下面这个栗子假设你编辑了 `hello.py` 文件的一些内容,并且准备好将它提交到项目历史。首先,你需要用 `git add` 缓存文件,然后提交缓存的快照。

```
git add hello.py
git commit
```
在 Git 等版本控制系统中,“保存”这个概念与我们熟悉的 Word 保存不太一样。传统软件里的“保存”对应的是 Git 里的“提交”(commit)。我们以前说的保存可以理解成是在文件系统中覆盖**一个**已有的文件或者创建**一个**新的文件。而在 Git 中,提交的操作对象可以是多个文件和目录。

它会打开一个文件编辑器(可以通过 `git config` 设置) 询问提交信息,同时列出将被提交的文件
Git 和 SVN 里保存更改的流程也有所区别。SVN 提交或检入(check-in)会将更新的内容推送到远端的中央服务器。也就是说,SVN 需要联网才能成功“保存”项目更改。Git 提交可以在本地完成,然后再通过`git push -u origin master`命令推送到远端服务器。这两种方法的差异体现了两种完全不同的架构设计。Git 是一个分布式的应用,而 SVN 是一个中心化的应用。一般来说分布式应用更可靠,因为中心化的服务器可能会导致单点故障

```
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
#modified: hello.py
```
`git add`、`git status`和`git commit`这三个命令通常一同使用,来将 Git 项目当前的状态保存成一份快照。

Git 对提交信息没有特定的格式限制,但约定俗成的格式是:在第一行用 50 个以内的字符总结这个提交,留一空行,然后详细阐述具体的更改。比如:
Git 还有另一个保存机制:“储藏”(stash)。储藏是一个临时的储存区域,仅仅存放尚未准备好提交的更改。储藏的作用对象是工作目录,也就是 Git 三个树状文件结构的第一个。它有很多用法,请访问 git stash 页面了解更多。

```
Change the message displayed by hello.py
你可以通过设置在保存时跳过 Git 仓库里一些文件或目录。Git 将不会保存这些文件的任何更改。Git 有多种方式可以管理忽略文件列表。请访问 git ignore 页面了解更多。

- Update the sayHello() function to output the user's name
- Change the sayGoodbye() function to a friendlier message
```
## 总结

注意,很多开发者倾向于在提交信息中使用一般现在时态。这样看起来更像是对仓库进行的操作,让很多改写历史的操作更加符合直觉
当你想要让 Git 将当前的项目状态保存成快照添加到提交历史中时,`git add` 是你要用到的第一个命令。单独使用时,`git add` 会将工作目录中的更改添加到缓存区。`git status` 命令用于检查仓库的当前状态。它能够帮助你判断 `git add` 操作成功与否。``git reset` 命令用于撤销 `git add` 命令。`git commit` 命令会发送一份缓存区的快照到仓库的提交历史

> 这篇文章是[**「git-recipes」**](https://github.com/geeeeeeeeek/git-recipes/)的一部分,点击 [**目录**](https://github.com/geeeeeeeeek/git-recipes/wiki/) 查看所有章节。
> 这篇文章是[**「git-recipes」**](https://github.com/geeeeeeeeek/git-recipes/)的一部分,点击 [**目录**](https://github.com/geeeeeeeeek/git-recipes/wiki/) 查看所有章节。
>
> 如果你觉得文章对你有帮助,欢迎点击右上角的 **Star** :star2: 或 **Fork** :fork_and_knife:。
>
Expand Down
77 changes: 77 additions & 0 deletions sources/2.3.1-git_add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Git add

![Saving changes](https://wac-cdn.atlassian.com/dam/jcr:75f75cb6-a6ab-4f0b-ab29-e366914f513c/hero.svg?cdnVersion=kg)

***[git add](2.3.1-git_add.md) / [git commit](2.3.2-git_commit.md) / [git diff](2.3.3-git_diff.md) / [git stash](2.3.4-git_stash.md) / [.gitignore](2.3.5-git_ignore.md)***

> ✍️ [童仲毅](https://github.com/geeeeeeeeek) | ⏳ 2018 年 12 月 1 日
>
> ©️ 本文演绎自 Atlassian 编写的 [_Saving Changes_](https://www.atlassian.com/git/tutorials/saving-changes)。页面上所有内容采用知识共享-署名([CC BY 2.5 AU](http://creativecommons.org/licenses/by/2.5/au/deed.zh))许可协议。

## git add

`git add` 命令将工作目录中的变化添加到缓存区。它告诉 Git 你希望下一个提交中包含这个文件的更新。不过,`git add` 不会实际上并不不会改变你的仓库——直到你运行 `git commit` 前更改都还不会真正被记录。

使用这些命令的同时,你还需要 `git status` 来查看工作目录和缓存区的状态。

## 工作原理

`git add` 和 `git commit` 这两个命令组成了最基本的 Git 工作流。每个 Git 用户都必须理解这两个命令,不管团队使用的是哪种协作模型。它们的作用是将项目的诸多版本记录到仓库历史中。

一个项目的编写离不开这个基本模式:编辑、缓存和提交。首先,你在工作目录中编辑你的文件。当你想要备份当前的项目状态时,你通过 `git add` 来缓存更改。当你觉得这个缓存的快照没问题了,你通过 `git commit` 将它提交到项目历史。`git reset` 命令用于撤销提交或缓存的快照。

除了 `git add` 和 `git commit` 之外,`git push` 也是完整的 Git 协作流程中的重要一环。`git push` 用于将提交的更改发送到远端仓库。操作完成后,其他团队成员也可以看到这些更改。

![Git Tutorial: git add Snapshot](https://wac-cdn.atlassian.com/dam/jcr:0f27e004-f2f5-4890-921d-65fa77ba2774/01.svg)

`git add` 命令和 `svn add` 不同。后者直接将**文件**添加到仓库中,而 `git add` 作用于更抽象的**更改**(更低一层)。也就是说,哪怕是同一个文件时,每次修改时你都需要使用 `git add` ,而 `svn add` 只需要使用一次。这听上去多此一举,但实际上使得项目更容易管理。

## 缓存区

`git add` 命令最主要的作用是将工作目录中的更改添加到 Git 的缓存区。缓存区是 Git 特有的功能之一,如果你之前使用的是 SVN(甚至是更古老的 Mercurial),那你可得花点时间理解了。你可以把它理解成工作目录和项目历史中间的缓冲区。缓存区是 Git 三个树状文件结构之一,另外两个是工作目录和提交历史。

缓存允许你把密切相关的一些更改合并成一份快照,而不是直接提交所有新的更改。也就是说你可以同时进行多个无关的更改,最后将相关的更改添加到缓存区,分成几次分别提交。对于任何版本控制系统来说,保持提交的原子性非常重要,以便于追踪 bug 以及用最小的代价撤销更改。

## 用法

```
git add <文件>
```

缓存 `<文件>` 中的更改,准备下次提交。

```
git add <目录>
```

缓存 `<目录>` 下的所有更改,准备下次提交。

```
git add -p
```

开始交互式的缓存,你可以将某个文件的其中一处更改加入到下次提交缓存。Git 会显示一堆更改,并等待用户命令。使用 `y` 缓存某一处更改,使用 `n` 忽略某一处更改,使用 `s` 将某一处分割成更小的几份,使用 `e` 手动编辑某一处更改,使用 `q` 退出编辑。

## 栗子

对于新项目来说,`git add` 和 `svn import` 的作用类似。使用下面两个命令为当前目录创建首个提交:

```
git add .
git commit
```

项目设置好之后,新的文件可以通过路径传递给 `git add` 来添加到缓存区:

```
git add hello.py
git commit
```

上面的命令同样可以用于记录已有文件的更改。重复一次,Git 不会区分被缓存的更改来自新文件,还是仓库中已有的文件。

> 这篇文章是[**「git-recipes」**](https://github.com/geeeeeeeeek/git-recipes/)的一部分,点击 [**目录**](https://github.com/geeeeeeeeek/git-recipes/wiki/) 查看所有章节。
>
> 如果你觉得文章对你有帮助,欢迎点击右上角的 **Star** :star2: 或 **Fork** :fork_and_knife:。
>
> 如果你发现了错误,或是想要加入协作,请参阅 [Wiki 协作说明](https://github.com/geeeeeeeeek/git-recipes/issues/1)。
Loading