git安装和基本使用
安装git
使用yum方式
$ sudo yum install git -y
源码方式安装
源码包获取地址
https://github.com/git/git/releases
安装依赖
$ sudo yum install gcc gcc-c++ curl-devel expat-devel gettext-devel \ openssl-devel zlib-devel asciidoc xmlto docbook2x
编译
$ tar -zxf git-2.24.1.tar.gz -C /opt $ cd /opt/git-2.24.1 $ make configure $ ./configure --prefix=/opt $ make all doc info $ sudo make install install-doc install-html install-info
升级git
$ git clone git://git.kernel.org/pub/scm/git/git.git
git配置
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。这些变量存储在三个不同的位置:
1. /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。 如果使用带有 --system 选项的git config 时,它会从此文件读写配置变量。
2. ~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 可以传递 --global 选项让 Git 读写此文件。
3. 当前使用仓库的 Git 目录中的 config 文件(就是 .git/config):针对该仓库。使用选项--local
每一个级别覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
设置用户信息
很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改:
$ git config --global user.name "zhang hao" $ git config --global user.email "416805766@qq.com" $ cat .gitconfig [user] name = zhang hao email = 416805766@qq.com
使用--global选项后,该命令只需要执行一次,因为git会记录用户的信息。
如果需要不同的用户名和邮件地址来管理不同项目,切到项目目录使用不带--global选项。
查看帮助
'git help -a' and 'git help -g' lists available subcommands and some concept guides. See 'git help <command>' or 'git help <concept>'
检查配置信息
$ git config --list user.name=zhang hao user.email=416805766@qq.com git config <key>: 来检查 Git 的某一项配置 $ git config user.name zhang hao
使用git仓库
初始化仓库
空目录初始化(该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件)
$ mkdir myproject $ cd myproject $ git init Initialized empty Git repository in /home/zhanghao/myproject/.git/ $ ll -a .git/ total 12 drwxrwxr-x 7 zhanghao zhanghao 119 Mar 10 16:16 . drwxrwxr-x 3 zhanghao zhanghao 18 Mar 10 16:16 .. drwxrwxr-x 2 zhanghao zhanghao 6 Mar 10 16:16 branches -rw-rw-r-- 1 zhanghao zhanghao 92 Mar 10 16:16 config -rw-rw-r-- 1 zhanghao zhanghao 73 Mar 10 16:16 description -rw-rw-r-- 1 zhanghao zhanghao 23 Mar 10 16:16 HEAD drwxrwxr-x 2 zhanghao zhanghao 242 Mar 10 16:16 hooks drwxrwxr-x 2 zhanghao zhanghao 21 Mar 10 16:16 info drwxrwxr-x 4 zhanghao zhanghao 30 Mar 10 16:16 objects drwxrwxr-x 4 zhanghao zhanghao 31 Mar 10 16:16 refs
非空目录初始化
如果在一个包含文件或包含非空目录的目录下初始化,可以使用 git add命令指定要追踪的文件,然后git commit提交。
$ mkdir cmdb $ touch cmdb/abc $ git init Initialized empty Git repository in /home/zhanghao/myproject/.git/ $ git add * $ git status # On branch master # # Initial commit # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: cmdb/abc # $ git commit -m "test" [master (root-commit) d321cd1] test 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 cmdb/abc
克隆仓库
在默认配置下,git clone命令会将远程仓库中的每个文件的每个版本都将拉取下来。
在磁盘损坏时,可以从任何一个克隆项目的客户端来重建仓库,不会丢失版本的数据。
$ git clone https://github.com/kubernetes/kubernetes.git Cloning into 'kubernetes'... 会在当前目录下创建一个kubernetes目录,并在这个目录下创建一个.git的目录,将所有clone的数据放入.git目录,然后从中读取最新版本文件的拷贝。 也可以指定clone后本地仓库的别名
$ git clone https://github.com/nginx/nginx.git mynginx
Cloning into 'mynginx'...
文件状态
git工作目录的文件只有两种状态:已追踪和未追踪。已追踪文件是指被纳入了版 本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区 。工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录 中,也没有放入暂存区。初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状 态。
使用 Git 时文件的生命周期如下 :
工作目录中文件状态检查
$ git status # On branch master nothing to commit, working directory clean 说明当前在mater分支,且目录中的文件自上次提交后从未更改过,所有文件都是未追踪状态。 $ echo 'test git' > readme $ git status # On branch master # Untracked files: # (use "git add <file>..." to include in what will be committed) # # readme nothing added to commit but untracked files present (use "git add" to track)
跟踪文件
使用git add跟踪
$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: readme #
暂存已修改文件
(1)修改文件
$ echo "changed" >> test.md $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: readme # new file: test.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: test.md
(2)将修改后的文件添加到暂存区
$ git add test.md $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: readme # new file: test.md
再次修改文件
$ echo 123 >test.md $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: readme # new file: test.md # # Changes not staged for commit: 又出现了此文件,说明对于此文件,保存的版本是上次git add时的版本,而不是commit时,在工作目录中的版本,需要再次git add # (use "git add <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # modified: test.md
$ git add test.md $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: readme # new file: test.md #
状态信息概述
使用git status -s命令可以查看状态概要信息,状态信息分两列,第一列和暂存区有关,第二列和工作目录有关。
A表示添加到暂存区的文件
M表示文件被修改过
??表示文件未跟踪
# 新建的文件显示状态??表示未追踪 $ echo "abc" >abc.txt $ git status -s AM readme A test.md ?? abc.txt ?? nginx/ # 将文件添加到暂存区后再修改文件,查看状态 $ git add abc.txt $ echo "def" > abc.txt $ git status -s AM abc.txt AM readme A test.md ?? nginx/ # 提交后再修改,就是在修改工作目录的文件。 $ git commit -m "test1" $ echo 123 >test.md $ git status -s M test.md ?? nginx/ $ echo "hello git" >readme $ git status -s M readme M test.md ?? nginx/ # 将文件添加到暂存区,再修改,左边暂存区状态也会出现M $ git add readme $ echo "dejavu huh?" >> readme $ git status -s MM readme M test.md ?? nginx/
.gitignore忽略文件
开发中,会希望一些文件不需要版本管理,也不希望这些文件出现在未追踪文件列表里,通常这些文件包括:编译过程中的临时文件、日志文件等。通过创建.gitignore文件来忽略这些文件。
[zhanghao@node4 myproject]$ touch batch.properties [zhanghao@node4 myproject]$ touch 12345.xml [zhanghao@node4 myproject]$ cat .gitignore *me nginx/*.c [zhanghao@node4 myproject]$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: .gitignore # new file: abc.txt # new file: cmdb/abc # new file: nginx # new file: test.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: .gitignore # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # 12345.xml # batch.properties [zhanghao@node4 myproject]$ vim .gitignore *me nginx/*.c *.xml [zhanghao@node4 myproject]$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: .gitignore # new file: abc.txt # new file: cmdb/abc # new file: nginx # new file: test.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: .gitignore # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # batch.properties
.gitignore文件的匹配规则及格式规范
所有空行或者以 # 开头的行都会被 Git 忽略。 可以使用标准的 glob 模式匹配. 匹配模式可以以(/)开头防止递归. 匹配模式可以以(/)结尾指定目录。 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号(!)取反。 *.a 表示忽略所有.a结尾的文件 !lib.a 表示忽略lib.a意外的所有文件,即只保留lib.a /TODO 表示仅忽略当前目录下的TODO目录 build/ 表示忽略build目录下的所有文件 doc/*.txt 表示忽略doc目录中以.txt结尾的文件 doc/**/*.pdf 表示忽略doc目录的所有子目录中以.pdf结尾的文件
.gitignore文件只对未追踪文件(untracked files)列表生效
[zhanghao@node4 myproject]$ vim .gitignore *me nginx/*.c *.xml *.txt [zhanghao@node4 myproject]$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: .gitignore # new file: abc.txt # new file: cmdb/abc # new file: nginx # new file: test.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: .gitignore # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # batch.properties
如果发现.gitignore没有生效,应该是由于有缓存导致,删除即可:
$ git rm -rf --cached . rm '.gitignore' rm 'abc.txt' rm 'cmdb/abc' rm 'nginx' rm 'test.md' $ git add . $ git commit -m "update Untracked files"
查看修改后文件的差异(git diff)
$ git status # On branch master nothing to commit, working directory clean $ cat readme dejavu huh? hello git $ echo "diff one" >> readme $ git add readme $ cat test.md 123 test diff $ sed -i '2c diff' test.md $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: readme # # 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: test.md # 此命令不加参数时,查看的是工作目录中文件和暂存区快照之间的差异。 $ git diff diff --git a/test.md b/test.md index 52c02e7..46af87d 100644 --- a/test.md +++ b/test.md @@ -1,2 +1,2 @@ 123 -test diff +diff
使用 --staged 或 --cached 参数查看暂存区的文件差异
[zhanghao@node4 myproject]$ git diff --staged diff --git a/readme b/readme index 71140b6..7a9e7a8 100644 --- a/readme +++ b/readme @@ -1,2 +1,3 @@ dejavu huh? hello git +diff one
提交更新
只会将暂存区的文件提交到版本库。
$ git commit -m "last commit" [master 47fc3a4] last commit 1 file changed, 1 insertion(+)
使用-a 选项可以跳过git add的步骤,将已追踪的文件提交
$ git commit -a -m "add not staged file" [master acdd5b4] add not staged file 1 file changed, 1 insertion(+), 1 deletion(-)
删除文件
只删除工作目录中的文件(此文件只是从)
可以看到删除的文件还在版本管理里 $ rm -rf nginx $ git commit -m "nginx" # On branch master # Changes not staged for commit: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: nginx # no changes added to commit (use "git add" and/or "git commit -a")
git rm 删除文件(下次提交时,被删除文件就不再版本里了),如果文件删除前修改过并且已加入到暂存区,需要使用 -f 选项删除
$ git rm nginx rm 'nginx' $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # deleted: nginx #
删除暂存区的文件git rm --cached
$ git rm --cached readme rm 'readme' $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # deleted: readme # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # readme
移动文件
$ git mv test.md test1.md $ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: test.md -> test1.md # git mv命令相当于执行了以下命令:工作目录移动文件,删除未暂存的文件,将未追踪的文件添加到暂存区
$ mv test.md test1.md $ git rm test.md $ git add test1.md 具体过程如下: [zhanghao@node4 myproject]$ mv test1.md test2.md [zhanghao@node4 myproject]$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: test.md -> test1.md # # Changes not staged for commit: # (use "git add/rm <file>..." to update what will be committed) # (use "git checkout -- <file>..." to discard changes in working directory) # # deleted: test1.md # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # test2.md [zhanghao@node4 myproject]$ git rm test1.md rm 'test1.md' [zhanghao@node4 myproject]$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # deleted: test.md # # Untracked files: # (use "git add <file>..." to include in what will be committed) # # test2.md [zhanghao@node4 myproject]$ git add test2.md
查看提交历史
[zhanghao@node4 ~]$ mkdir progit [zhanghao@node4 ~]$ cd progit [zhanghao@node4 progit]$ git clone https://github.com/schacon/simplegit-progit Cloning into 'simplegit-progit'... remote: Enumerating objects: 13, done. remote: Total 13 (delta 0), reused 0 (delta 0), pack-reused 13 Unpacking objects: 100% (13/13), done. 默认不用任何参数的话,git log 会按提交时间列出所有的更新,最近的更新排在最上面 $ cd simplegit-progit/ $ git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 10:31:28 2008 -0700 first commit
-p 查看每次提交的内容差异(所有的提交)
$ git log -p commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ require 'rake/gempackagetask' spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "simplegit" - s.version = "0.1.0" + s.version = "0.1.1" s.author = "Scott Chacon" s.email = "schacon@gmail.com" s.summary = "A simple gem for using Git in Ruby code." commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code diff --git a/lib/simplegit.rb b/lib/simplegit.rb index a0a60ae..47c6340 100644 --- a/lib/simplegit.rb +++ b/lib/simplegit.rb @@ -18,8 +18,3 @@ class SimpleGit end end - -if $0 == __FILE__ - git = SimpleGit.new - puts git.show -end \ No newline at end of file commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 10:31:28 2008 -0700 first commit diff --git a/README b/README new file mode 100644 index 0000000..a906cb2 --- /dev/null +++ b/README @@ -0,0 +1,6 @@ +SimpleGit Ruby Library +====================== + +This library calls git commands and returns the output. + +Author : Scott Chacon \ No newline at end of file diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..a874b73 --- /dev/null +++ b/Rakefile @@ -0,0 +1,23 @@ +require 'rubygems' +Gem::manage_gems +require 'rake/gempackagetask' + +spec = Gem::Specification.new do |s| + s.platform = Gem::Platform::RUBY + s.name = "simplegit" + s.version = "0.1.0" + s.author = "Scott Chacon" + s.email = "schacon@gmail.com" + s.summary = "A simple gem for using Git in Ruby code." + s.files = FileList['lib/**/*'].to_a + s.require_path = "lib" +end + +Rake::GemPackageTask.new(spec) do |pkg| + pkg.need_tar = true +end + +task :default => "pkg/#{spec.name}-#{spec.version}.gem" do + puts "generated latest version" +end + diff --git a/lib/simplegit.rb b/lib/simplegit.rb new file mode 100644 index 0000000..a0a60ae --- /dev/null +++ b/lib/simplegit.rb @@ -0,0 +1,25 @@ +# a super simple example class to use git in ruby +class SimpleGit + + def initialize(git_dir = '.') + @git_dir = File.expand_path(git_dir) + end + + def show(treeish = 'master') + command("git show #{treeish}") + end + + private + + def command(git_cmd) + Dir.chdir(@git_dir) do + return `#{git_cmd} 2>&1`.chomp + end + end + +end + +if $0 == __FILE__ + git = SimpleGit.new + puts git.show +end \ No newline at end of file
-p -N <int> 查看最近n次提交的差异
[zhanghao@node4 simplegit-progit]$ git log -p -2 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number diff --git a/Rakefile b/Rakefile index a874b73..8f94139 100644 --- a/Rakefile +++ b/Rakefile @@ -5,7 +5,7 @@ require 'rake/gempackagetask' spec = Gem::Specification.new do |s| s.platform = Gem::Platform::RUBY s.name = "simplegit" - s.version = "0.1.0" + s.version = "0.1.1" s.author = "Scott Chacon" s.email = "schacon@gmail.com" s.summary = "A simple gem for using Git in Ruby code." commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code diff --git a/lib/simplegit.rb b/lib/simplegit.rb index a0a60ae..47c6340 100644 --- a/lib/simplegit.rb +++ b/lib/simplegit.rb @@ -18,8 +18,3 @@ class SimpleGit end end - -if $0 == __FILE__ - git = SimpleGit.new - puts git.show -end \ No newline at end of file
查看每次提交差异的概要信息 --stat
[zhanghao@node4 simplegit-progit]$ git log --stat commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 16:40:33 2008 -0700 removed unnecessary test code lib/simplegit.rb | 5 ----- 1 file changed, 5 deletions(-) commit a11bef06a3f659402fe7563abf99ad00de2209e6 Author: Scott Chacon <schacon@gmail.com> Date: Sat Mar 15 10:31:28 2008 -0700 first commit README | 6 ++++++ Rakefile | 23 +++++++++++++++++++++++ lib/simplegit.rb | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+) [zhanghao@node4 simplegit-progit]$ [zhanghao@node4 simplegit-progit]$ [zhanghao@node4 simplegit-progit]$ [zhanghao@node4 simplegit-progit]$ git log --stat -1 commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon <schacon@gmail.com> Date: Mon Mar 17 21:52:11 2008 -0700 changed the verison number Rakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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(后跟指定格式)。 |
常用输出选项
选项 | 说明 |
-(n) | 仅显示最近的 n 条提交 |
--since, --after | 仅显示指定时间之后的提交。 |
--until, --before | 仅显示指定时间之前的提交。 |
--author | 仅显示指定作者相关的提交。 |
--committer | 仅显示指定提交者相关的提交。 |
--grep | 仅显示含指定关键字的提交 |
-S | 仅显示添加或移除了某个关键字的提交 |
修改提交信息
[zhanghao@node4 simplegit-progit]$ git commit -m "initial commit" [zhanghao@node4 simplegit-progit]$ touch test [zhanghao@node4 simplegit-progit]$ git add test [zhanghao@node4 simplegit-progit]$ git commit --amend # 一下为--amend选项使用后,弹出的编辑界面,将此文件第一行改为要替换的提交信息 changed the verison number # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Author: Scott Chacon <schacon@gmail.com> # # On branch master # Changes to be committed: # (use "git reset HEAD^1 <file>..." to unstage) # # modified: Rakefile # new file: test
回滚
$ echo "abc" >> test $ git add test $ git status # On branch master # Your branch and 'origin/master' have diverged, # and have 1 and 1 different commit each, respectively. # (use "git pull" to merge the remote branch into yours) # # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: test $ git reset HEAD test Unstaged changes after reset: M test $ git status # On branch master # Your branch and 'origin/master' have diverged, # and have 1 and 1 different commit each, respectively. # (use "git pull" to merge the remote branch into yours) # # 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: test #
撤销对文件的修改
$ git mv README README.txt $ git status # On branch master # Your branch and 'origin/master' have diverged, # and have 3 and 1 different commit each, respectively. # (use "git pull" to merge the remote branch into yours) # # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: README -> README.txt # $ echo "3124" >> README.txt $ git status # On branch master # Your branch and 'origin/master' have diverged, # and have 3 and 1 different commit each, respectively. # (use "git pull" to merge the remote branch into yours) # # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # renamed: README -> README.txt
posted on 2020-03-11 18:36 hopeless-dream 阅读(635) 评论(0) 编辑 收藏 举报