Git由浅入深之操作与指令

来源:Git由浅入深之操作与指令
作者:惊鸿三世(转载已获得原作者许可,如需转载请与原作者联系)

本篇正式开始介绍Git的基础操作与原理,看完本篇,你应该知道如何使用Git进行一次基础的版本控制,包括:Git仓库的生成和获取,添加和忽略版本控制对象;暂存,查看,缓存,变更;查看和查找提交历史;格式化历史记录输出;删除和移动Git仓库内对象。

获取Git仓库(Git repository)

使用Git的第一步是要获取一个Git仓库,我们使用Git的操作对象都是存放在Git仓库里,获取Git仓库的方式有两种:

  • 导入一个项目或目录到Git,初始化(init)生成Git仓库;
  • 从远程服务器克隆(clone)一个Git仓库。

初始化仓库(init)

若我们需要使用一个项目或目录生成一个Git仓库,只需要通过命令行进入该目录,执行如下Git指令:

git init

此操作将在此目录生成一个.git子目录,该目录包含整个仓库结构,即仓库的所有文件;同时会检出(checkout)一个默认工作分支,通常名为master。

此时,我们只是初始化生成了一个Git仓库,还未添加需要进行版本控制的对象–文件或目录。

克隆仓库(clone)

很多时候,我们需要从远程服务器获取一个已存在的Git仓库,我们只需要使用如下指令:

git clone https://github.com/codingplayboy/javascript_notes

git clone后面跟着的url就是已存在的Git仓库地址,我们需要知道的是Git克隆是对服务器上仓库的一次近乎完整的数据拷贝,当前仓库项目的所有文件及其各版本历史都会被获取。

执行如上指令后,会在当前目录创建一个javascript_notes目录并在javascript_notes中初始化一个.git子目录,拉取仓库的所有数据,然后根据仓库(或项目)的最新版本检出(check out)一个工作分支,通常该分支默认名称为master。

仓库别名

我们克隆一个Git仓库时,其默认名还是仓库名,但是也支持我们自定义本地别名:

git clone https://github.com/codingplayboy/javascript_notes js_notes

执行如上指令,会克隆一个仓库,并导入到当前目录下的js_notes目录。

仓库Url

Git仓库Url支持的协议有很多,最常见的是https://git@;还有使用SSH传输协议的,形如git://或者user@server:path/xxx/repository.git

版本控制对象

在上节,我们已经知道如何获取一个Git仓库,但是到目前为止也仅仅是存在一个仓库,我们进行版本控制的对象(文件或目录)并没有添加进仓库。

工作目录及其内对象的状态

相关指令:git status

当我们获取一个仓库,如克隆一个远端仓库后,在仓库目录执行上面指令,如图所示:

  • 图中第一行on branch master 告诉我们当前我们处在名为master的分支;
  • 第二行up-to-date with 'origin/master' 说明目前分支与远程仓库的master分支保持同步最新版本;
  • 第三行working directory clean 说明目前仓库中没有新加或修改过的对象(文件或目录)。

关于控制对象的状态(git status)

在当前工作目录的文件或目录,可能出于两种状态:

  • 已标记(tracked)

所谓已标记文件或目录,即那些在Git最新快照里存在的对象,可能是未修改(unmodified),已修改(modified)或暂存(staged)的文件或目录。

  • 未标记(untracked)

未标记对象,即除去已标记对象外,所有对象,比如在工作目录下但是未包含在最新快照里并且不在暂存区(staging area)。

可以想象一下,当第一次克隆一个远程仓库后,仓库下的所有文件都应该是处于已标记(tracked)但是未修改的状态。

添加对象(git add)

添加版本控制对象的指令是git add,比如,我们可以使用如下指令添加一个README.txt文件,当然我们首先需要在仓库目录下,创建该文件(任意方式创建),查看状态:

如上图,显示README.txt文件为Untracked file,并且提示:use git add to track;

然后使用git add指令后:

git add README.txt

再次执行git status指令:

如上,出现:Changes to be committed,说明该文件已被标记(tracked)且被暂存,我们可以进行提交了。

当然该指令还可以对目录使用:

git add test/

如上指令,将添加该test目录及其内所有文件或子目录。

最后,也许我们希望一次添加所有变更,而不是一个一个添加,如下指令,可以实现:

git add .

我们还需要关注git add指令,不只是能添加版本控制对象,还有以下功能:

  • 暂存变更(staged)
  • 标记冲突已解决(resolved)

git add指令,更贴切的作用应该是添加新内容(文件/目录/变更)到下一次提交,即将新内容加入最新快照,等待提交;
关于后两点功能,后文有详细介绍。

忽略对象(.gitignore)

有时候,我们并不希望对仓库内所有对象(文件或目录)进行管理,某些开发依赖或本地调试使用文件和目录,我们不需要在团队间共享,这些文件应该被Git忽略,我们只需要创建一个.gitignore文件,在此文件中列出希望被忽略的文件或目录,如:

.gitignore文件语法主要如下:

  • 以行为单位,一行匹配一个条件
  • 空行或以#开头的行会被忽略
  • 表达式支持glob格式
  • 排除某表达式匹配项在该表达式前加!;

暂存变更(git add)

在添加README.txt文件后,我们可以对其进行修改,如在该文件加入一行文字http://blog.codingplayboy.com,然后执行git status指令,结果如下:

发现,除了之前新添加文件的记录,又多了一条记录:Changes not staged for commit,表明已标记对象发生变更但是未被暂存,其下面第一第二行是辅助信息,第三行告诉我们,README.txt已经修改(modified)

随后我们可以使用git add指令暂存此次变更,此时,再执行git status指令,可以看到:

所有变更都已暂存,等待下一次提交。

查看简短状态信息(git status -s)

上文已经指出,使用git status可以查看当前工作目录完整的状态,同时,git还支持使用参数指明查看简短状态信息:

git status -s
or 
git status --short

如下,其信息比git status简洁明了:


查看变更信息(git diff)

前文的git status可以查看当前工作目录的状态信息,包括当前分支,变更文件等,但都属于文件层次的信息;

有时我们希望知道:

  • 哪些变更未被暂存;
  • 哪些变更已暂存,等待提交

git status显然是不能告诉我们,因为这是属于git diff的使命,如,在README.txt文件中内容添加‘/’

如上图,git diff以行为单位,告诉我们所有变更文件哪些行发生变更(增加或删除)。

git diff比较当前工作目录和暂存区的内容,然后展示哪些文件内容发生变更并且尚未暂存;同时,其支持额外参数--staged(或–cached),该参数指定时,将输出上次提交内容与暂存区内容比较后的的变更。简言之,git diff输出未暂存的变更,git diff --staged输出已暂存待提交的变更。

在使用git add .暂存变更后,使用git diff指令是没用的,而使用git diff --staged指令,输出如下:

提交变更(git commit)

所有的变更,最终都需要提交,才能在本地持久化报存,在将所有变更暂存(git add)后,我们就可以进行提交了,相关指令就是:

git commit

在输入如上指令后,将进入Git commit信息编辑状态:

我们可以编辑本次提交的备注信息,其中的默认备注信息都以#开头,表明提交时会被忽略。

git commit指令告诉Git持久化记录(提交)我们暂存区(staging area)中的快照,任何未被暂存的变更,不会被添加进暂存区的快照,仍然保留在当前工作目录,我们可以随后提交。

更详细的提交信息(git commit -v)

除了使用默认的git commit指令,我们还可以添加-v参数,在提交信息中显示变更内容,如下:

如上图,和之前的比较,除了基本的提示,还有文件变更内容提示,可以避免某些误提交。

行内输入提交信息(git commit -m)

当然,Git还支持我们使用-m参数,指明我们在使用git commit指令时直接填写提交备注信息:

跳过暂存区(git commit -a)

我们知道对于发生变更的对象,我们需要先使用git add,暂存变更,再使用git commit提交变更;

但是还有一种可以不使用git add指令的方式,可以提交变更,就是给git commit指令添加-a参数:

git commit -a

但是需要注意的是,该参数,只能直接提交工作目录中已标记的对象(文件或目录)的变更,对于未标记,如新添加的对象,是无效的。

查看提交历史(Git log)

本节要介绍的是如何查看之前的提交历史及信息,你应该知道的git log指令,默认地,不带参数时,执行git log指令,输出的是当前仓库按逆序排序(最近提交在最前)的提交记录:

如上图,每个提交记录包含其SHA-1校验和,提交者用户名,提交日期,提交备注信息。

git log指令支持指定许多参数,以过滤输出不同提交记录,下文展开介绍。

指定查看提交记录数(git log -2)

Git支持我们指定数量参数,限定该次查看提交记录数量,如git log -2,之后输出最近的两条提交记录。

格式化输出提交记录(git log –pretty)

Git支持我们格式化输出的提交记录信息,使用–pretty参数,其值主要有以下几个:

  • oneline: 指定一行输出一条提交记录;
  • short: 指定按原格式输出简要信息;
  • full: 指定按原格式输出信息;
  • fuller: 指定按原格式输出更多信息;
  • format:””: 允许指定自定义输出格式,如:
git log --pretty=format:"%h - %an, %ar : %s"

查看简要提交变更(git log –stat)

git log --stat输出如下:

除了输出基础提交信息,后面还输出了本次提交的简要变更信息:变更了多少文件,及每个文件变更的行数,并在最后输出总结数据。

查看详细提交变更(git log -p)

相对于git log --stat输出简要提交变更信息,我们可以指定-p参数:git log -p,输出提交变更的详细内容,如:

更多参数说明

| 参数 | 说明 |

来源:Git由浅入深之操作与指令
作者:惊鸿三世(转载已获得原作者许可,如需转载请与原作者联系)

本篇正式开始介绍Git的基础操作与原理,看完本篇,你应该知道如何使用Git进行一次基础的版本控制,包括:Git仓库的生成和获取,添加和忽略版本控制对象;暂存,查看,缓存,变更;查看和查找提交历史;格式化历史记录输出;删除和移动Git仓库内对象。

获取Git仓库(Git repository)

使用Git的第一步是要获取一个Git仓库,我们使用Git的操作对象都是存放在Git仓库里,获取Git仓库的方式有两种:

  • 导入一个项目或目录到Git,初始化(init)生成Git仓库;
  • 从远程服务器克隆(clone)一个Git仓库。

初始化仓库(init)

若我们需要使用一个项目或目录生成一个Git仓库,只需要通过命令行进入该目录,执行如下Git指令:

git init

此操作将在此目录生成一个.git子目录,该目录包含整个仓库结构,即仓库的所有文件;同时会检出(checkout)一个默认工作分支,通常名为master。

此时,我们只是初始化生成了一个Git仓库,还未添加需要进行版本控制的对象–文件或目录。

克隆仓库(clone)

很多时候,我们需要从远程服务器获取一个已存在的Git仓库,我们只需要使用如下指令:

git clone https://github.com/codingplayboy/javascript_notes

git clone后面跟着的url就是已存在的Git仓库地址,我们需要知道的是Git克隆是对服务器上仓库的一次近乎完整的数据拷贝,当前仓库项目的所有文件及其各版本历史都会被获取。

执行如上指令后,会在当前目录创建一个javascript_notes目录并在javascript_notes中初始化一个.git子目录,拉取仓库的所有数据,然后根据仓库(或项目)的最新版本检出(check out)一个工作分支,通常该分支默认名称为master。

仓库别名

我们克隆一个Git仓库时,其默认名还是仓库名,但是也支持我们自定义本地别名:

git clone https://github.com/codingplayboy/javascript_notes js_notes

执行如上指令,会克隆一个仓库,并导入到当前目录下的js_notes目录。

仓库Url

Git仓库Url支持的协议有很多,最常见的是https://git@;还有使用SSH传输协议的,形如git://或者user@server:path/xxx/repository.git

版本控制对象

在上节,我们已经知道如何获取一个Git仓库,但是到目前为止也仅仅是存在一个仓库,我们进行版本控制的对象(文件或目录)并没有添加进仓库。

工作目录及其内对象的状态

相关指令:git status

当我们获取一个仓库,如克隆一个远端仓库后,在仓库目录执行上面指令,如图所示:

  • 图中第一行on branch master 告诉我们当前我们处在名为master的分支;
  • 第二行up-to-date with 'origin/master' 说明目前分支与远程仓库的master分支保持同步最新版本;
  • 第三行working directory clean 说明目前仓库中没有新加或修改过的对象(文件或目录)。

关于控制对象的状态(git status)

在当前工作目录的文件或目录,可能出于两种状态:

  • 已标记(tracked)

所谓已标记文件或目录,即那些在Git最新快照里存在的对象,可能是未修改(unmodified),已修改(modified)或暂存(staged)的文件或目录。

  • 未标记(untracked)

未标记对象,即除去已标记对象外,所有对象,比如在工作目录下但是未包含在最新快照里并且不在暂存区(staging area)。

可以想象一下,当第一次克隆一个远程仓库后,仓库下的所有文件都应该是处于已标记(tracked)但是未修改的状态。

添加对象(git add)

添加版本控制对象的指令是git add,比如,我们可以使用如下指令添加一个README.txt文件,当然我们首先需要在仓库目录下,创建该文件(任意方式创建),查看状态:

如上图,显示README.txt文件为Untracked file,并且提示:use git add to track;

然后使用git add指令后:

git add README.txt

再次执行git status指令:

如上,出现:Changes to be committed,说明该文件已被标记(tracked)且被暂存,我们可以进行提交了。

当然该指令还可以对目录使用:

git add test/

如上指令,将添加该test目录及其内所有文件或子目录。

最后,也许我们希望一次添加所有变更,而不是一个一个添加,如下指令,可以实现:

git add .

我们还需要关注git add指令,不只是能添加版本控制对象,还有以下功能:

  • 暂存变更(staged)
  • 标记冲突已解决(resolved)

git add指令,更贴切的作用应该是添加新内容(文件/目录/变更)到下一次提交,即将新内容加入最新快照,等待提交;
关于后两点功能,后文有详细介绍。

忽略对象(.gitignore)

有时候,我们并不希望对仓库内所有对象(文件或目录)进行管理,某些开发依赖或本地调试使用文件和目录,我们不需要在团队间共享,这些文件应该被Git忽略,我们只需要创建一个.gitignore文件,在此文件中列出希望被忽略的文件或目录,如:

.gitignore文件语法主要如下:

  • 以行为单位,一行匹配一个条件
  • 空行或以#开头的行会被忽略
  • 表达式支持glob格式
  • 排除某表达式匹配项在该表达式前加!;

暂存变更(git add)

在添加README.txt文件后,我们可以对其进行修改,如在该文件加入一行文字http://blog.codingplayboy.com,然后执行git status指令,结果如下:

发现,除了之前新添加文件的记录,又多了一条记录:Changes not staged for commit,表明已标记对象发生变更但是未被暂存,其下面第一第二行是辅助信息,第三行告诉我们,README.txt已经修改(modified)

随后我们可以使用git add指令暂存此次变更,此时,再执行git status指令,可以看到:

所有变更都已暂存,等待下一次提交。

查看简短状态信息(git status -s)

上文已经指出,使用git status可以查看当前工作目录完整的状态,同时,git还支持使用参数指明查看简短状态信息:

git status -s
or 
git status --short

如下,其信息比git status简洁明了:


查看变更信息(git diff)

前文的git status可以查看当前工作目录的状态信息,包括当前分支,变更文件等,但都属于文件层次的信息;

有时我们希望知道:

  • 哪些变更未被暂存;
  • 哪些变更已暂存,等待提交

git status显然是不能告诉我们,因为这是属于git diff的使命,如,在README.txt文件中内容添加‘/’

如上图,git diff以行为单位,告诉我们所有变更文件哪些行发生变更(增加或删除)。

git diff比较当前工作目录和暂存区的内容,然后展示哪些文件内容发生变更并且尚未暂存;同时,其支持额外参数--staged(或–cached),该参数指定时,将输出上次提交内容与暂存区内容比较后的的变更。简言之,git diff输出未暂存的变更,git diff --staged输出已暂存待提交的变更。

在使用git add .暂存变更后,使用git diff指令是没用的,而使用git diff --staged指令,输出如下:

提交变更(git commit)

所有的变更,最终都需要提交,才能在本地持久化报存,在将所有变更暂存(git add)后,我们就可以进行提交了,相关指令就是:

git commit

在输入如上指令后,将进入Git commit信息编辑状态:

我们可以编辑本次提交的备注信息,其中的默认备注信息都以#开头,表明提交时会被忽略。

git commit指令告诉Git持久化记录(提交)我们暂存区(staging area)中的快照,任何未被暂存的变更,不会被添加进暂存区的快照,仍然保留在当前工作目录,我们可以随后提交。

更详细的提交信息(git commit -v)

除了使用默认的git commit指令,我们还可以添加-v参数,在提交信息中显示变更内容,如下:

如上图,和之前的比较,除了基本的提示,还有文件变更内容提示,可以避免某些误提交。

行内输入提交信息(git commit -m)

当然,Git还支持我们使用-m参数,指明我们在使用git commit指令时直接填写提交备注信息:

跳过暂存区(git commit -a)

我们知道对于发生变更的对象,我们需要先使用git add,暂存变更,再使用git commit提交变更;

但是还有一种可以不使用git add指令的方式,可以提交变更,就是给git commit指令添加-a参数:

git commit -a

但是需要注意的是,该参数,只能直接提交工作目录中已标记的对象(文件或目录)的变更,对于未标记,如新添加的对象,是无效的。

查看提交历史(Git log)

本节要介绍的是如何查看之前的提交历史及信息,你应该知道的git log指令,默认地,不带参数时,执行git log指令,输出的是当前仓库按逆序排序(最近提交在最前)的提交记录:

如上图,每个提交记录包含其SHA-1校验和,提交者用户名,提交日期,提交备注信息。

git log指令支持指定许多参数,以过滤输出不同提交记录,下文展开介绍。

指定查看提交记录数(git log -2)

Git支持我们指定数量参数,限定该次查看提交记录数量,如git log -2,之后输出最近的两条提交记录。

格式化输出提交记录(git log –pretty)

Git支持我们格式化输出的提交记录信息,使用–pretty参数,其值主要有以下几个:

  • oneline: 指定一行输出一条提交记录;
  • short: 指定按原格式输出简要信息;
  • full: 指定按原格式输出信息;
  • fuller: 指定按原格式输出更多信息;
  • format:””: 允许指定自定义输出格式,如:
git log --pretty=format:"%h - %an, %ar : %s"

查看简要提交变更(git log –stat)

git log --stat输出如下:

除了输出基础提交信息,后面还输出了本次提交的简要变更信息:变更了多少文件,及每个文件变更的行数,并在最后输出总结数据。

查看详细提交变更(git log -p)

相对于git log --stat输出简要提交变更信息,我们可以指定-p参数:git log -p,输出提交变更的详细内容,如:

更多参数说明

参数 说明
-p 显示详细提交变更
–stat 显示简要提交变更
–shortstat 在–stat参数输出基础上只输出修改,新增或删除的行
–name-only 显示提交时发生变更的文件名
–name-status 显示提交时发生变更的文件名,并显示变更类型(删除,新增,或修改)
–abbrev-commit 只显示提交记录SHA-1校验和的前几个字符
–relative-date 显示简要提交日期(如, “2 weeks ago”)
–graph 显示分支提交历史的ASCII图
–pretty 支持预定义输出格式,详细说明见上文

过滤提交历史输出

Git支持我们在输出历史记录时,添加多种过滤条件,最简单的比如-<num>参数条件,指定输出最近的若干条提交记录,还有诸如提交时间,提交作者等条件。

  • –since/–after:git log --since=2.weeks
    输出两周内的提交记录,参数值还可以形如”2016-01-15″,”2 years 1 day 10 minutes ago”

  • –until/–before: git log --until=2016-01-15

  • –grep: git log --grep=README
    可以指定关键字,只有提交信息中存在关键字才会输出

  • –author: 过滤输出指定提交作者的记录

  • –commiter: 输出满足指定commiter的提交记录

  • -S: git -log -Swebpack
    输出提交内容(代码或文件或目录)包含指定字符串的记录

删除对象(git rm)

很多时候,我们也会需要从Git仓库中删除某些对象,rm就是删除文件或目录的指令,但是需要特别强调的是,该指令只是将某对象从当前工作目录删除,如:


使用rm后,当前状态是”Changes not staged for commit:”此次变更未被暂存和提交。

若你需要将某对象从已标记文件或暂存区删除,则需要使用git rm指令,如下:


使用git rm后,变更会被暂存。

强制删除(git rm -f)

当我们发生某次变更,且将其添加到暂存区(index索引),我们只使用git rm指令是不行的:


我们必须加上-f参数,指明强制删除。

缓存变更(git rm –cached)

有时候,我们在某次变更添加了某文件(甚至可能已经添加到暂存区),但是暂时不需要提交,又不想直接删除它,即只在工作目录存在,而不将其放入暂存区,只需要添加--cached参数,如修改README.txt同时,新增了test.txt文件,并且暂存了变更,之后提交时我们不希望此次提交test.txt,但又不希望删除它,则在提交前使用git rm --cached test.txt

移动对象(git mv)

通常,我们也许需要移动或重命名某文件或目录,Git有mv指令,还要一个更方便的指令git mv,如:

git mv a.txt b.txt

另一方面,重命名或移动某文件或目录,这两个操作对于Git来说是没有太大区别的,比如上面的重命名文件操作等效于:

mv a.txt b.txt
git rm a.txt
git add b.txt

我们可以看到git mv指令是在mv指令操作的基础上暂存此次操作的变更,而mv只是一个重命名或移动指令,不涉及版本控制流程。

到此,Git的基本使用,已经介绍完成,不过,本篇讲解的基础操作,都是在计算机本地进行的版本控制,并没有同步到服务器,那么下一篇的主题就出来了:Git如何与远程服务器进行协同工作。

往期文章

更多干货内容请关注:极乐科技

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容