Git 常用命令学习

​​ Remote:远程仓库 Repository:本地仓库

​​ Workspace: 工作区 Index: 暂存区


安装Git

Windows

​ 在官网下载安装程序, 然后按默认选项安装即可。

​ 安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!

Linux

​ 系统版本:CentOS 7.3,x86_64 , root用户

​ 查看系统是否已安装git :git --version , 如果提示bash: /usr/bin/git: No such file or directory,则说明系统中还没有安装git; 如果显示了git 版本号,则证明系统中已经安装了git。

​ Redhat系的Linux发行版,安装git最便捷的方法是直接使用yum 安装:yum install git , 但是经过测试,CentOS 7.3 通过yum 安装的Git 版本默认为v1.8.3 , 而目前git最新版本为v2.16.0,低版本的git存在安全漏洞,所以不建议使用yum安装,推荐使用源码安装git.

  1. 卸载已经安装的低版本的git:yum remove git

  2. 安装git依赖包

sudo yum groupinstall "Development Tools" 
sudo yum install -y curl-devel expat-devel gettext-devel openssl-devel perl-CPAN perl-devel zlib-devel
  1. 依赖包安装完成后,需要找出并 下载最新版本的git,,位于列表顶部的是最新版本,注意不要选择带有-rc的版本,因为它代表了一个候选发布版本。

    选择最新的版本 ,使用wget下载:

wget https://github.com/git/git/archive/v2.15.1.tar.gz
  1. 安装git
#解压
tar -zxvf git.tar.gz 
#编译
cd git*   #进入git解压目录
make configure
./configure   --prefix=/usr/local/
make prefix=/usr/local/ all
make install
  1. 查看版本 git --version , 如果显示的git版本还是v1.8或提示找不到git目录,执行命令:cp /usr/local/bin/git* /usr/bin/ ,就可以了。

设置Git

​ 设置你的一些个人信息,如你提交的姓名和电子邮件:

$ git config --global user.name 'shijianzhihu'
$ git config --global user.email 'shijianzhihu@foxmail.com'

#查看所有已配置的全局信息
$ git config --list 

Git 常用命令

以下所有的命令说明都基于Git v2.13.0,不同版本的Git ,命令可能会有所区别!
git --version #查看git 版本
git [command] --help #查看command用户手册

git clone

git clone 用来从从远程主机克隆一个版本库,语法为:git clone <版本库地址> ,该命令会在本地主机生成一个与远程主机版本库同名的目录,如果要指定不同的目录名,可以将目录名作为git clone命令的第二个参数:
git clone <版本库的网址> <本地目录名>

git remote

Git要求每个远程主机都必须指定一个主机名。git remote命令就用于管理主机名.

#查看所有远程主机名
$ git remote
origin

#查看远程主机地址
$ git remote -v
origin  https://github.com/naver/ngrinder.git (fetch)
origin  https://github.com/naver/ngrinder.git (push)

git fetch

一旦远程主机的版本库有了更新,需要将这些更新取回本地,这时就要用到git fetch命令.

#将远程主机的所有分支的更新取回本地
$ git fetch <远程主机名>
如:git fetch origin

#取回指定分支的更新
$ git fetch <远程主机名> <分支名>
如:git fetch origin dev

git branch

git branch 用来显示、创建或删除分支。

OPTIONS

  1. 不带参数,会列出所有本地分支,并且在当前分支前加"*";
$ git branch
  dev
  master
* test
  1. git branch <newBranch> 新建本地分支,但不会自动切换到该分支
$ git branch bug-fixed
  1. <-r, --remotes> 列出所有远程分支
$ git branch -r
  origin/bug-fixed
  origin/b2b
  origin/beta
  origin/collections
  origin/chart
  1. <-a --all> 列出所有本地分支和远程分支
$ git branch -a
  1. <-m ,--move | -M> 移动/重命名一个分支和相应的历史信息
# <-M>:强制move/rename
$ git branch -m bug-fixed bug-fixed2
  1. <-d, --delete | -D> 删除本地分支,不能删除当前checkout的分支;
    如果要删除的分支有未合并的内容,则会报错:'the branch XXX is not fully merged',解决办法:使用'-D' 强制删除;
$ git branch -D 'bug-fixed'

# 补充:利用管道命令实现批量删除分支
$ git branch | grep 'branchName' | xargs branch -D
  1. <-v, --verbose>
# 查看本地分支最后的修改信息,当前分支名称前会带有'*'
$ git branch -av
  bug-fixed3 fdcbdf7 add bug -fixed2
  dev        1599863 test
* master     9faecaf [ahead 1] update test.txt  #[ahead 1]表示本地分支比远程分支领先一个commit
  test       1599863 test
  remotes/origin/HEAD       -> origin/master
  remotes/origin/bug-fixed3 fdcbdf7 add bug -fixed2

git checkout

git checkout 用来切换分支或恢复工作树文件。

OPTIONS

  1. git checkout <branch> 切换当前分支到本地已有分支
$ git checkout dev
Switched to branch 'dev'

新建本地分支,并切换到该分支

$ git checkout -b five
Switched to a new branch 'five'

新建本地分支,并切换到该分支,而且关联远程分支(必须已存在 否则报错)

$ git checkout -b six --track origin/dev
Switched to a new branch 'six'
Branch six set up to track remote branch dev from origin.

第三条命令相当于以下命令的合集:

$ git branch 
$ git checkout six
$ git branch --set-upstream-to origin/dev six
  1. git checkout <-- fileNmae> 注意 '--' 和 'fileName' 之间有空格!作用是将指定文件在工作区的修改撤销到最近一次git add 或git commit时的内容(只对tracked file有效),比如下面的例子:
$ cat test.txt
one
$ git add . -v
add 'test.txt'
$ git commit -m 'update test.txt'
[test a2d987d] update test.txt
 1 file changed, 1 insertion(+)

# 此时再去修改文件内容
$ vim test.txt
$ cat test.txt
one
two

# 撤销修改
$ git checkout -- test.txt #注意空格,否则报错
$ cat test.txt
one
$ git status 
nothing to commit, working tree clean

需要一次撤销多个文件的修改时,支持以下写法:

$ git checkout -- stu.txt test.txt
$ git checkout -- *
$ git checkout -- *.txt
  1. git checkout -- 不加文件名来查看当前工作区修改了哪些文件, 和git status效果差不多
$ git checkout --
M       blog.txt
D       start.txt
Your branch is up-to-date with 'origin/sprider'.
  1. 取文件在commit_id时的版本
$ git checkout 1599863 fileName

git status

git status 用来显示工作树状态, git会非常友好的提示用户下一步的操作,请看下面的例子:

$ git status
On branch test
Your branch is up-to-date with 'origin/test'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        blog.txt

nothing added to commit but untracked files present (use "git add" to track)

$ git add blog.txt

$ git status
#
On branch test
Your branch is up-to-date with 'origin/test'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   blog.txt

$ git commit -m 'add blog.txt'
$ git status
On branch test
Your branch is ahead of 'origin/test' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

git add

git add命令主要用于把我们要提交的文件的信息添加到索引库(Index)中。当我们使用git commit时,git将依据索引库中的内容来进行文件的提交。git add命令可以在commit之前多次执行。

git add file

COMMON OPTIONS

#可以使用'*'模糊匹配路径, 且路径可以到目录层级
$ git add *.c
$ git add test/

<-v,--verbose>
#显示本次added的文件名
$ git add -v file3.txt
add 'file3.txt'
$ git add -v study/
add 'study/study.txt'

<-f, --force>
#允许添加被忽略的文件
$ git add -f commonVars.pyc

<-u, --update>
#add被修改(modified)和被删除(deleted)文件,不包含新文件(new,untracked file)
$ git add -uv

<-A, --all>
#add所有变化,包括被修改(modified)、被删除(deleted)文件和包括新文件(new)
$ git add -Afv

git add -A | git add -u |git add .

  • git add .:他会监控工作区的状态树,使用它会把工作时的所有变化提交到暂存区,包括modified、new和deleted ;
  • git add -u:他仅监控已经被add的文件(即tracked file),他会将被修改的文件提交到暂存区。add -u 不会提交new(untracked file);
  • git add -A:等同于 git add .;
    注意,在Git v1.x.x版本,git add . 不能添加deleted文件

git 特殊文件

有些时候,我们必须或被必须把某些文件放到Git的工作目录中,但是又不能提交它们。这就导致每次git status都会显示Untracked files ... 。为了解决这个文件,可以在Git工作区的根目录下创建一个特殊的.gitignore文件,这个文件的作用就是告诉Git哪些文件不需要添加到版本管理中。实际项目中,很多文件都是不需要版本管理的,比如Python的.pyc文件和一些包含密码的配置文件等等。这个文件的内容是一些规则,Git会根据这些规则来判断是否将文件添加到版本控制中。

GitHub中已经为我们准备了各种配置文件,只需要组合一下就可以使用了。所有配置文件可以直接在线浏览:https://github.com/github/gitignore
常用的规则有:

1. /mtk/        #过滤整个文件夹
2. *.zip          #过滤所有.zip文件
3. /mtk/do.c   #过滤某个具体文件

忽略文件的原则是:

  • 忽略操作系统自动生成的文件,比如缩略图等;
  • 忽略编译生成的中间文件、可执行文件等,也就是如果一个文件是通过另一个文件自动生成的,那自动生成的文件就没必要放进版本库,比如Java编译产生的.class文件;
  • 忽略你自己的带有敏感信息的配置文件,比如存放口令的配置文件。

gitignore文件中添加新过滤文件,但是此文件已经提交到远程库,可以使用以下方式如何解决:

第一步,为避免冲突需要先同步下远程仓库
$ git pull origin 

第二步,在本地项目目录下删除缓存
$ git rm -r --cached . 

第三步,再次add所有文件
输入以下命令,再次将项目中所有文件添加到本地仓库缓存中
$ git add .

第四步,添加commit,提交到远程库
$ git commit -m "filter new files"
$ git push origin

git commit

git commit 记录对存储库的更改信息,此命令默认提交的是暂存区的内容,也就是 Changes to be committed 中的文件,最常用的参数是<-m>,用来添加本次提交的相关信息,如:git commit -m 'update file'

如果使用了<-a>参数,则除了将暂存区里的文件提交外,还提交 Changes but not updated 中的文件。通常我们提交git的时候都是通过以下三大步:

git add .
git commit -m "some str"
git push

实际上,你只需要两条命令就够了,除非有新的文件(untracked file)要被添加进去。

git commit -am "some str"
git push

git pull

git pull命令的作用是,取回远程主机指定分支的更新,再与本地的指定分支合并。实质上等同于先做git fetch,再做git merge.

命令的完整格式为:

$ git pull <远程主机名> <远程分支名>:<本地分支名>

比如:取回origin主机的bugifx分支与本地的bugfix2分支合并,需要写成下面这样

git pull origin bugfix:bugfix2

如果远程分支是与当前分支合并,则本地分支名可以省略

$ git pull origin dev

如果当前分支与远程分支存在关联关系,远程分支名也可以省略

$ git pull origin

如果当前分支只有一个追踪分支,则远程主机名也可以省略,以下命令表示为:当前分支自动与唯一一个远程追踪分支进行合并

$ git pull

如果合并需要使用rebase模式,可以加上'-- rebase'选项

$ git pull --rebase <远程主机名> <远程分支名>:<本地分支名>

如果远程主机删除了某个分支,默认情况下,git pull 不会在拉取远程分支的时候,删除对应的本地分支。这是为了防止,由于其他人操作了远程主机,导致git pull不知不觉删除了本地分支。但是,你可以改变这个行为,加上参数 -p 就会在本地删除远程已经删除的分支。

$ git pull -p
# 等同于下面的命令
$ git fetch --prune origin 
$ git fetch -p

git push

git push命令用于将本地分支的更新,推送到远程主机。它的命令格式与git pull命令相仿但不要搞混了,其实很容易理解区分的.

#完整格式
$ git push <远程主机名> <本地分支名>:<远程分支名>

#如果省略远程分支名,则表示将本地分支推送与之存在"追踪关系"的远程分支(通常两者同名)
#如果该远程分支不存在,则会被新建。
$ git push origin dev

#如果省略本地分支名,则表示删除指定的远程分支,因为这表示推送一个空的本地分支到远程分支。
#注意origin 和冒号之间需要有空格
$ git push origin :dev

#如果当前分支与远程分支存在关联关系,远程分支名也可以省略
$ git push origin
如果当前分支与远程分支没有追踪关系,则会报错:
fatal: The current branch bug-fixed2 has no upstream branch.
To push the current branch and set the remote as upstream, use
    git push --set-upstream origin bug-fixed2
    
#如果当前分支只有一个追踪分支,则远程主机名也可以省略
$ git push

git log | git reflog

git log 用来查看当前分支的提交历史,不包含已经被撤销的commit:

$ git log
commit 150089329868f665cfd6a1f1ac301d31ff232c75 (HEAD -> sprider)
Author: xxxxx <shijianzhihu@foxmail.com>
Date:   Tue Feb 6 14:14:06 2018 +0800
    Revert "test"
    This reverts commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459.
commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459
Author: xxxxx <shijianzhihu@foxmail.com>
Date:   Tue Feb 6 14:13:54 2018 +0800
    test

如果嫌输出信息太多,以试试加上--oneline参数:

$ git log --oneline
1500893 (HEAD -> sprider) Revert "test"
5e2d6fc test
a0eb8b5 update blog.txt
ec9734c Revert "start test"
1616640 Revert "blog"

显示每次提交的内容差异可以使用< -p> 参数,<-n>则为仅显示最近的n次历史:

$ git log -p -1
commit 150089329868f665cfd6a1f1ac301d31ff232c75 (HEAD -> sprider)
Author: xxxxx <shijianzhihu@foxmail.com>
Date:   Tue Feb 6 14:14:06 2018 +0800
    Revert "test"
    This reverts commit 5e2d6fc0bd652de0e612e50b84edb9b933d2d459.
diff --git a/blog b/blog
index 40a3b4a..9daeafb 100644
--- a/blog
+++ b/blog
@@ -1 +1 @@
-test111
+test

git reflog 用来显示整个本地仓储的commit, 包括所有branch的commit, 甚至包括已经撤销的commit, 只要HEAD发生了变化(如checkout branch, pull, commit等), 就会在reflog里面看得到。

$ git reflog
1500893 (HEAD -> sprider) HEAD@{0}: checkout: moving from six to sprider
02cffe0 (six) HEAD@{1}: commit: branch six
1599863 (origin/dev, five) HEAD@{2}: checkout: moving from sprider to six
1500893 (HEAD -> sprider) HEAD@{3}: revert: Revert "test"
5e2d6fc HEAD@{4}: commit: test

git revert | git reset

git revert 用来回滚一些现有的提交, 但并不是从项目历史中移除这个commit,旧的commit还是保留在历史项目里面的,而git reset 则会删除旧的commit。

用法: git revert <commit-id>

$ git log --oneline | head -n 1
a0eb8b5 update blog.txt

$ git revert HEAD
[sprider 60d4654] Revert "update blog.txt"
 1 file changed, 1 insertion(+), 2 deletions(-)
 
$ git log --oneline | head -n 2
60d4654 Revert "update blog.txt"
a0eb8b5 update blog.txt

git reset <--hard|soft|mixed|merge|keep> commitID 也是常用的版本回滚命令,其中比较重要的参数是mode,也就是 --hard、--soft、--mixed... 比较常见的是--hard和--soft:

  1. --hard是指完全重设,会把回退到某版本之后的修改全部删除,
  2. --soft这是个回退解体,让版本库回退到某个版本,这个版本之后的修改全部存在缓存区,这个时候在commit的话,又会把会退的部分重新加载到最新版本中;

git diff

git diff用于比较两次修改之间的差异。

  • 比较工作区与暂存区

git diff 不加参数即默认比较工作区与暂存区

$ git diff
diff --git a/b2.txt b/b2.txt
index be738a5..2ffe5d8 100644
--- a/b2.txt
+++ b/b2.txt
@@ -1,2 +1,2 @@
 test1
-test222
+22dsada2
  • 比较暂存区与最新本地版本库
    git diff --cached
  • 比较工作区与最新本地版本库
    git diff HEAD
  • 比较工作区与指定commit-id的差异
    git diff commit-id
  • 比较暂存区与指定commit-id的差异
    git diff --cached commit-id
  • 比较两个commit-id之间的差异
    git diff commit-id commit-id

git stash

git stash 用来备份当前的工作区的内容,从最近的一次提交中读取相关内容,让工作区保证和上次提交的内容一致。同时,将当前的工作区内容保存到Git栈中。

  • git stash list 显示Git栈内的所有备份,可以利用这个列表来决定从那个地方恢复。
  • git stash clear 清空Git栈.
  • git stash pop 从Git栈中读取最近一次stash的内容,恢复工作区的相关内容。

两种恢复方法:

  • 用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
  • 用git stash pop,恢复的同时把stash内容也删了;

可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:
git stash apply stash@{0}

git rm

git rm用于从从工作树和暂存区中删除文件,他作用的对象只能是tracked files .

它的作用和git add 类似,可以理解为一个是添加一个是修改。git rm 要和git commit 配合使用,才真正能起到删除的作用。

$ git rm test.txt stu.txt
rm 'stu.txt'
rm 'test.txt'
$ git status
On branch test
Your branch is up-to-date with 'origin/test'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        deleted:    stu.txt
        deleted:    test.txt
$ git commit -m 'delete two files'
[test ccd7143] delete two files
 2 files changed, 4 deletions(-)
 delete mode 100644 stu.txt
 delete mode 100644 test.txt
$ git status
On branch test
Your branch is ahead of 'origin/test' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working tree clean

#删除文件夹,-r表示递归删除,-f表示强制删除
$ git rm -rf qt/ 
rm 'qt/file.txt'

$ git rm -f rainbow.txt #不能对untracked file使用
fatal: pathspec 'rainbow.txt' did not match any files

git rm 和 rm 的区别

通过上面简单的介绍,我们发现git rm 和 shell 命令rm 非常相似,我们是否可以不使用git rm,而是直接rm后,然后再git add/commit,这样是否可以呢? 答案当然是可以的。

使用git rm来删除文件,git同时会将操作日历记录下来,git log就可以看到;而使用rm来删除文件,git并不会记录,这也是十分易于理解的。直观的来讲,git rm 删除过的文件,执行 git commit -m "abc"提交时,会自动将删除该文件的操作提交上去;而对于用 rm 命令直接删除的文件,执行 git commit -m "abc" 提交时,则不会将删除该文件的操作提交上去。不过不要紧,即使你已经通过 rm 将某个文件删除掉了,也可以再通过 git rm 命令重新将该文件从 git 的记录中删除掉,这样的话,在执行 git commit -am "abc"后,也能将这个删除操作提交上去。(git commit -am 写成git commit -ma 会报错)

一般说来,在git目录下删除文件时,可以选择以下两种方式:

  • git rm + git commit -m 'text'
  • rm + git commit -am 'text'

git mv

git mv 用来移动或重命名文件、目录或符号链接。

$ git mv b1.txt b2.txt
$ git mv rainbow.txt sprider/
$ git status
On branch sprider
Your branch is ahead of 'origin/sprider' by 1 commit.
  (use "git push" to publish your local commits)
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
        renamed:    b1.txt -> b2.txt
        renamed:    rainbow.txt -> sprider/rainbow.txt
        
$ git commit -m 'rename and move'
[sprider b08e44d] rename and move
 2 files changed, 0 insertions(+), 0 deletions(-)
 rename b1.txt => b2.txt (100%)
 rename rainbow.txt => sprider/rainbow.txt (100%)

参考文档

  1. Git 教程,廖雪峰

  2. Git远程操作详解,阮一峰

  3. Git忽略规则.gitignore梳理 ,散尽浮华

  4. git的reset和checkout的区别,chanjarster

  5. git add -A 和 git add . 的区别 ,PajamaCat

  6. git branch用法总结 ,KKK_Kevin

  7. Git自学之路(四) - gitbranch 分支,JunkChen-程开均

  8. Git中的upstream和downstream概述,易生一世

  9. “git rm” 和“rm”的区别,jfkidear

  10. git commit -m与git commit -am的区别

  11. Git的撤消操作 - 重置, 签出 和 撤消

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

推荐阅读更多精彩内容