Git Blame
# 查看文件中,每一行的修改人和最后改動(dòng)時(shí)間
$ git blame pom.xml
^e81ccde3 (BenedictJin 2018-06-04 11:16:19 +0800 1) <?xml version="1.0" encoding="UTF-8"?>
Git Branch
# 克隆當(dāng)前分支,以此創(chuàng)建新的 branch,并切換
$ git checkout -b <branch>
# 重命名 branch 名稱
$ git branch -m <old_name> <new_name>
$ git branch -m <new_name>
# 恢復(fù)刪除掉的 branch
# 查看你上一次 commit SHA1 值
$ git reflog
# 恢復(fù)
$ git branch <branch_name> <sha1>
Git Cache
# 添加 .gitignore 文件之后,可能有些文件報(bào)錯(cuò) `ignored tracked with git`
# 需要用 `git rm --cached` 進(jìn)行刪除
$ git rm --cached <file>
# 部分動(dòng)態(tài)文件可能報(bào)錯(cuò)文件內(nèi)容不一致 `the following files have staged content different from both the file and the HEAD`
# 需要增加 `-f` 參數(shù)進(jìn)行強(qiáng)制刪除
$ git rm --cached -f .idea/workspace.xml
Git Cherry-pick
# 從遠(yuǎn)程倉(cāng)庫(kù)中,指定某一次提交,合并到當(dāng)前分支中
$ git cherry-pick 5738c801c
Git Checkout
checkout 的同時(shí),創(chuàng)建新的 branch
$ git checkout -b <new_branch_new>
撤銷某個(gè)文件的修改
$ git checkout -- <file>
Git Config
$ git config user.name "asdf2014"
$ git config user.email "yuzhouwan@gmail.com"
$ git reset .
$ git add -A
$ git diff --staged
Git Commit
Commit Merge
常規(guī)操作
$ git log --pretty=oneline
651cc60d971aba93bdde645b6331c33068462645 Merge branch 'master' of https://github.com/asdf2014/superset
415610958494446ccd37c0c87da98eba56af42ac Merge branch 'temp'
b881140282893fa4add183a2b3f2637968f95069 Merge branch 'master' into master
f2bf3160583533bd0dc5004f248f81251aa8c57e Add NUMERIC num_type (#2127)
6a0fefdbd542da4ea313313a191eadd1efe58faa Using the time zone with specific name for querying Druid
9cd38fa1eda63152c27b76c29dd948f29444b686 little code refactor in models.py (#2124)
$ git reset --soft HEAD~2 &&
$ git commit --edit -m "$($ git log --format=%B --reverse HEAD..HEAD@{1})"
[master fd41c16] Add NUMERIC num_type (#2127)
1 file changed, 1 insertion(+), 1 deletion(-)
# 更改之后的 commit 信息
fd41c1608579408fcd26d0dd03adf0d461599101 Add NUMERIC num_type (#2127)
6a0fefdbd542da4ea313313a191eadd1efe58faa Using the time zone with specific name for querying Druid
9cd38fa1eda63152c27b76c29dd948f29444b686 little code refactor in models.py (#2124)
踩到的坑
Failed to push some refs
描述
Username for 'https://github.com': asdf2014
To https://github.com/asdf2014/superset.git
! [rejected] ext_deprecation_warning -> ext_deprecation_warning (non-fast-forward)
error: failed to push some refs to 'https://github.com/asdf2014/superset.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: '$ git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in '$ git push --help' for details.
解決
# 強(qiáng)制提交
$ git push -u origin ext_deprecation_warning --force
Commit Remove
$ git reset --hard <sha1-commit-id>
$ git push origin HEAD --force
Commit Change
只修改最后一次提交
# 格式
$ git commit --amend
$ git commit --amend -m "New commit message"
$ git commit --amend --author="Author Name <email@address.com>"
# 示例
$ git commit --amend -m 'remove warnings.simplefilter from cli.py into superset for PEP (#2137)'
$ git commit --amend --author="asdf2014 <yuzhouwan@gmail.com>"
修改之前的提交信息
$ git rebase -i HEAD~2
pick xxxx
reword yyyy
修改提交的日期
# 查看當(dāng)前時(shí)間
$ date -R
Mon, 07 Jan 2018 11:12:55 +0800
# 修改最后一次 commit 的提交日期
$ git commit --amend --date="Mon, 07 Jan 2018 12:00:00 +0800"
# 更新提交日期為當(dāng)前時(shí)間
$ git commit --amend --date="$(date -R)"
Reset into Specific Commit
# It will make your local code and local history be just like it was at that commit. But then if you wanted to push this to someone else who has the new history, it would fail.
$ git reset --hard c14809fa
# It will make your local files changed to be like they were then, but leave your history etc. the same.
$ git reset --soft c14809fa
Squash Commits into a Single Commit
常規(guī)操作
# 查看哪些 commits 需要進(jìn)行合并
$ git log --pretty=oneline
# 合并最后 11 個(gè) commit
$ git rebase -i HEAD~11
pick xxxx yyyy
pick xxxx yyyy
pick xxxx yyyy
# 將需要壓縮的 commit 之前的 `pick` 替換為 `squash`
pick xxxx yyyy
squash xxxx yyyy
squash xxxx yyyy
$ git commit --amend -m 'The log length has exceeded the limit of 4 MB in Travis'
$ git push origin travis_log --force
# 如需解決沖突后,繼續(xù)進(jìn)行 rebase 操作,可執(zhí)行
$ git rebase --continue
# 如果想中斷 rebase 操作,則執(zhí)行
$ git rebase --abort
# 更多細(xì)節(jié)
$ git rebase --help
其他
回滾
$ git reset --hard ORIG_HEAD
回滾上一次操作
$ git commit -m "Something terribly misguided"
$ git reset HEAD~
<< edit files as necessary >>
$ git add ...
$ git commit -c ORIG_HEAD
指定 commit number
$ git rebase <commit number>
合并 branch 改動(dòng)到 master 中
# 會(huì)將 branch 里的 commit 排到 master 的頂部,避免帶 Merge 信息的 `空 commit` 出現(xiàn)
$ git checkout <branch name>
$ git rebase -i master
# 如果已經(jīng)在當(dāng)前 branch 執(zhí)行了 git merge master,并解決了沖突,可以直接執(zhí)行下面這行命令,完成 rebase 操作
$ git rebase --root --onto master --preserve-merges
# 萬(wàn)一出現(xiàn)太多的問題,難以解決,可以采用如下暴力的方式(在意 commit 信息的,請(qǐng)預(yù)先備份好)
$ git rebase --abort # 首先 abort 之前的 rebase 流程
$ git checkout code_refactoring
$ git checkout -b re2
$ git branch root bbb61e638b391d29 # 以當(dāng)前 branch 未做任何修改之前的 commit 為基礎(chǔ),創(chuàng)建 root 分支
$ git checkout re2
$ git diff master > ../123.patch # 當(dāng)前 branch 相對(duì) master 已經(jīng)做的修改打出 patch 文件
$ git checkout master
$ git checkout -b r2
$ git apply ../123.patch # 以 master 為基礎(chǔ),apply 分支上做的修改
$ git diff master
$ git status
$ git diff --name-status | wc -l # 確認(rèn)修改的文件數(shù) 是否正確
$ git add .
$ git status
$ git diff master
$ git commit -m 'Improve `collection` related things that reusing a immutable object instead of creating a new object'
$ git status
$ git push origin r2:code_refactoring -f
Git Diff
Git diff two commits
$ git diff 1285c982 b0aaa7de > v3.4.6_vs_v3.4.10.patch
Git diff two branchs
$ git diff branch_1..branch_2
Git Fetch
Normal
# Github 上對(duì)某一個(gè)開源項(xiàng)目進(jìn)行 fork
https://github.com/apache/superset
https://github.com/asdf2014/superset (forked from apache/superset)
# 本地獲取 fork 出來(lái)的 asdf2014/superset
$ git init
$ git remote add origin https://github.com/asdf2014/superset.git
$ git remote -v
origin https://github.com/asdf2014/superset.git (fetch)
origin https://github.com/asdf2014/superset.git (push)
## 發(fā)現(xiàn)并沒有 airbnb/superset 的 origin/master,可以在直接往 asdf2014/superset 提交,然后在 github 上進(jìn)行 pull request 的創(chuàng)建
https://github.com/apache/superset/pull/2136 (Fix werkzeug instance was created twice in Debug Mode (#2135) #2136)
$ git fetch https://github.com/apache/superset.git master:tmp
$ git diff tmp
$ git merge tmp
$ git branch -d tmp
Fetch all tags
$ git fetch --tags
$ git checkout tags/release-3.4.6
$ git checkout master
Previous HEAD position was 1285c982... ZooKeeper 3.4.6 release.
Switched to branch 'master'
Git Merge
# 如果不希望 PR 中的 comment 信息被沖掉,可以使用 `git merge` 替代 `git rebase`
$ git merge
# 如果存在沖突,解決后,執(zhí)行如下兩個(gè)命令
$ git add .
$ git merge --continue
Git Reflog
恢復(fù) git reset --hard
# 找到 reset 操作的
$ git reflog
2a93709d (HEAD -> yuzhouwan, origin/yuzhouwan) HEAD@{0}: reset: moving to 631cc5233063bb014587a9caf0c9e3095fe6a60e
b5b67779 HEAD@{1}: commit: Something important
# 回滾到 reset 操作前的一次提交
$ git reset --hard b5b67779
Git Remote
Change remote url
$ git remote set-url origin <url>
Pull specific tag from remote
$ git pull origin release-1.7.7:release-1.7.7
同時(shí) push 到多個(gè)倉(cāng)庫(kù)
$ git remote set-url --add origin git@github.com:asdf2014/draft.git
$ git remote -v
origin https://git.coding.net/BenedictJin/test.git (fetch)
origin https://git.coding.net/BenedictJin/test.git (push)
origin git@github.com:asdf2014/test.git (push)
刪除遠(yuǎn)程倉(cāng)庫(kù)
$ git remote rm origin
Git Reset
回退某一個(gè)文件的修改
$ git reset HEAD^ yuzhouwan.txt
Git Rm
清理緩存
描述
某些已經(jīng)被加到 .gitignore 的文件提示,ignored, tracked with git
解決
# 單個(gè)文件
$ git rm --cached <file>
# 整個(gè)項(xiàng)目
$ git rm -r --cached .
# add 變更內(nèi)容,并切換到 tmp 分支,commit 后,再刪除 tmp 分支
$ git add .
$ git checkout -b tmp
$ git commit -m 'Remove ignored files'
$ git checkout master
$ git branch -D tmp
Git Stash
# 查看當(dāng)前分支已經(jīng)存在的改動(dòng)
$ git status
On branch exception_governance
Your branch is up to date with 'origin/exception_governance'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: a
# 臨時(shí)保存當(dāng)前分支的修改
$ git stash
Saved working directory and index state WIP on exception_governance: d5062a04 Govern old error codes and their exceptions
# 查看已經(jīng)臨時(shí)保存的改動(dòng)
$ git stash list
stash@{0}: WIP on exception_governance: d5062a04 Govern old error codes and their exceptions
# 已經(jīng)看到修改已經(jīng)被隱藏了
$ git add .
$ git diff --staged
# 再次從 stash 中恢復(fù)出之前的修改
$ git stash pop
On branch exception_governance
Your branch is up to date with 'origin/exception_governance'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: a
Dropped refs/stash@{0} (a88e4f6d681eb59b9b22e800f2c00f4c9e22d529)
Git Tag
Create tag
# 創(chuàng)建簡(jiǎn)單的標(biāo)簽
$ git tag v0.0.1
# 創(chuàng)建帶有附注的 tag
$ git tag -a v0.0.2 -m "v0.0.2"
# 展示 tag 信息
$ git show v0.0.2
# 給指定的 commit,打 tag
$ git tag -a v0.0.3 6d23400
Submit tag
$ git push origin v0.0.2
# push 本地所有標(biāo)簽
$ git push origin –tags
Pull with specific tag
$ git clone
# 列出 tag 列表,并 checkout 到指定的 tag
$ git tag -l
$ git checkout tags/<tag_name>
# checkout 到指定的 tag,并創(chuàng)建一個(gè)新的 branch
$ git checkout tags/<tag_name> -b <branch_name>
Delete tag
# 刪除本地 Tag
$ git tag -d v3.4.6.0
Deleted tag 'v3.4.6.0' (was 0e48a03a)
# 刪除遠(yuǎn)程 Tag
$ git push origin :refs/tags/v3.4.6.0
To http://github.com/asdf2014/zookeeper.git
- [deleted] v3.4.6.0
Git 編輯器切換為 Notepad++
# 命令行設(shè)置
$ git config --global core.editor "'D:/apps/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
# 修改配置文件
$ vim ~/.gitconfig
[core]
editor = 'D:/apps/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin
Git 代理
通過命令設(shè)置
$ git config --global http.proxy 'http://192.168.1.101:8888'
$ git config --global https.proxy 'https://192.168.1.101:8888'
$ git config --global http.proxy 'socks5://127.0.0.1:1080'
$ git config --global https.proxy 'socks5://127.0.0.1:1080'
通過配置文件設(shè)置
$ vim ~/.ssh/config
[http]
proxy = http://192.168.1.101:8888
[https]
proxy = https://192.168.1.101:8888
# [http]
# proxy = socks5://127.0.0.1:1080
# [https]
# proxy = socks5://127.0.0.1:1080
踩過的坑
SSL_ERROR_SYSCALL in connection to git.coding.net:443
描述
$ git push origin master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (9/9), done.
Writing objects: 100% (9/9), 1.05 KiB | 1.05 MiB/s, done.
Total 9 (delta 6), reused 0 (delta 0)
error: RPC failed; curl 35 OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to git.coding.net:443
fatal: The remote end hung up unexpectedly
fatal: The remote end hung up unexpectedly
Everything up-to-date
解決
# 先確保 git 和 curl 版本不能過低,如果 git <2.60 或者 curl <7.29,則需要升級(jí)到最新版本
$ git --version
$ curl --version
# 打開 git 命令的 trace 日志
$ export GIT_CURL_VERBOSE=1
$ export GIT_TRACE_PACKET=2
# 再次執(zhí)行出錯(cuò)命令
$ git push origin master
// ...
error: RPC failed; curl 7 Failed to connect to 127.0.0.1 port 1080: Connection refused
fatal: The remote end hung up unexpectedly
Everything up-to-date
# 通過日志分析,定位出是 proxy 的問題,關(guān)閉 proxy 即可
參考
Git 中文亂碼
$ git config --global core.quotepath false # 顯示 status 編碼
$ git config --global gui.encoding utf-8 # 圖形界面編碼
$ git config --global i18n.commit.encoding utf-8 # 提交信息編碼
$ git config --global i18n.logoutputencoding utf-8 # 輸出 log 編碼
$ export LESSCHARSET=utf-8 # `git log` 默認(rèn)使用 `less` 分頁(yè),所以需要 `bash` 對(duì) `less` 命令進(jìn)行 `utf-8` 編碼
# 讓 `ls` 命令可以顯示中文名稱
$ vim %GIT_HOME%\mingw64\share\git\completion\git-completion.bash
# 在文件末尾處添加一行
alias ls="ls --show-control-chars --color"
Github 加速
# Ctrl + R(管理員權(quán)限運(yùn)行)
# notepad "%SystemRoot%\system32\drivers\etc\hosts"
# https://asm.ca.com/zh_cn/ping.php
192.30.253.112 github.com
151.101.56.133 assets-cdn.github.com
192.30.253.116 api.github.com
192.30.253.121 codeload.github.com
# 中國(guó) - 香港特別行政區(qū)(hkhkg02)
192.30.253.112 github.com
151.101.100.133 assets-cdn.github.com
192.30.253.116 api.github.com
192.30.253.121 codeload.github.com
Patch
$ git diff > patch
$ git apply patch
參考
SSH 免密
常規(guī)操作
# 如果沒有 .ssh 隱藏文件,則需要先打開 `git bash`,并執(zhí)行
$ mkdir ~/.ssh
$ chmod +700 ~/.ssh
$ cd ~/.ssh
$ ssh-keygen -t rsa -C "yuzhouwan@email.com"
# 將 ~/.ssh/id_rsa.pub 中的公鑰加入 github/gitlab
$ ssh -T git@github.com
Hi asdf2014! You've successfully authenticated, but GitHub does not provide shell access. '
# http -> ssh
$ git remote -v
origin https://github.com/asdf2014/yuzhouwan (fetch)
origin https://github.com/asdf2014/yuzhouwan (push)
$ git remote set-url origin git@github.com:asdf2014/yuzhouwan.git
$ git remote -v
origin git@github.com:asdf2014/yuzhouwan.git (fetch)
origin git@github.com:asdf2014/yuzhouwan.git (push)
如何在代理環(huán)境下,同時(shí)支持 github / gitlab / coding 的免密操作
場(chǎng)景介紹
-
github.com和coding.net需要走代理訪問 -
gitlab是自建的私服
PAC 配置
在任何 git 相關(guān)操作之前,需要先配置 PAC 文件,來(lái)保證本機(jī)網(wǎng)絡(luò)的暢通
var domains = {
"coding.net": 1,
"git.coding.net": 1,
"github.com": 1,
"ssh.github.com": 1
};
var proxy = "__PROXY__";
var direct = 'DIRECT;';
var hasOwnProperty = Object.hasOwnProperty;
function FindProxyForURL(url, host) {
var suffix;
var pos = host.lastIndexOf('.');
pos = host.lastIndexOf('.', pos - 1);
while(1) {
if (pos <= 0) {
if (hasOwnProperty.call(domains, host)) {
return proxy;
} else {
return direct;
}
}
suffix = host.substring(pos + 1);
if (hasOwnProperty.call(domains, suffix)) {
return proxy;
}
pos = host.lastIndexOf('.', pos - 1);
}
}
SSH 配置
在配置 SSH 之前,同樣需要保證 ssh 命令使用的網(wǎng)絡(luò)代理是正確的
首先,找到 connect 命令安裝路徑
$ which connect
/mingw64/bin/connect
$ which connect.exe
/mingw64/bin/connect.exe
其次,修改 ~/.ssh/config 文件
Host github.com
User git
Port 22
Hostname github.com
IdentityFile ~/.ssh/id_rsa # 這里也可以填寫絕對(duì)路徑
TCPKeepAlive yes
IdentitiesOnly yes
ProxyCommand /mingw64/bin/connect.exe -H 127.0.0.1:1080 %h %p
Host ssh.github.com
User git
Port 443
Hostname ssh.github.com
IdentityFile ~/.ssh/id_rsa
TCPKeepAlive yes
IdentitiesOnly yes
ProxyCommand /mingw64/bin/connect.exe -H 127.0.0.1:1080 %h %p
Host git.coding.net
User <email> # coding.net 這里比較特殊,需要填寫注冊(cè)的郵箱地址
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa
TCPKeepAlive yes
IdentitiesOnly yes
ProxyCommand /mingw64/bin/connect.exe -H 127.0.0.1:1080 %h %p
Host yuzhouwan.gitlab.com
User git
Port 22
Hostname yuzhouwan.gitlab.com
IdentityFile ~/.ssh/id_rsa
TCPKeepAlive yes
IdentitiesOnly yes
然后,生成私鑰、公鑰,并分別拷貝公鑰到 github / gitlab / coding 服務(wù)器中,具體操作見上文描述
最后,驗(yàn)證
$ ssh -T git@github.com
Hi asdf2014! You've successfully authenticated, but GitHub does not provide shell access.
$ ssh -T git@yuzhouwan.gitlab.com
Welcome to GitLab, BenedictJin!
$ ssh -T git@git.coding.net
Coding 提示: Hello BenedictJin, You've connected to Coding.net via SSH. This is a personal key.
BenedictJin,你好,你已經(jīng)通過 SSH 協(xié)議認(rèn)證 Coding.net 服務(wù),這是一個(gè)個(gè)人公鑰
保持從 fork 端更新代碼
# 申明 fork 端的倉(cāng)庫(kù)地址
$ git remote add upstream git@gitlab.yuzhouwan.com:asdf2014/yuzhouwan.git
# check 是否添加正確
$ git remote -v
origin git@gitlab.yuzhouwan.com:asdf2018/yuzhouwan.git (fetch)
origin git@gitlab.yuzhouwan.com:asdf2018/yuzhouwan.git (push)
upstream git@gitlab.yuzhouwan.com:asdf2014/yuzhouwan.git (fetch)
upstream git@gitlab.yuzhouwan.com:asdf2014/yuzhouwan.git (push)
# 更新所有的分支
$ git fetch upstream
# 指定更新某一個(gè)分支,這里以 master 分支為例
$ git fetch upstream master
# 使用 fork 端的 master 分支進(jìn)行 rebase
$ git rebase upstream/master
代碼風(fēng)格配置
Intellij Idea
# download: http://www.arminalter.com/public/img/attach/checkstyle/eclipse-java-google-style.xml
File - Settings - Editor - Code Style - Schema - Manage - Import - Eclipse XML Profile
File - Settings - Plugins - "CheckStyle-IDEA"
# download: http://www.arminalter.com/public/img/attach/checkstyle/google_checks.xml
File - Setting - Other Settings - Check Style(+) # 如果這里使用的是 帶有變量的 xml 文件,需要正確指定對(duì)應(yīng)的 value 值
File - Settings - Editor - Inspections - Checkstyle real-time scan(√) # 開啟實(shí)時(shí) check code style
# 一般的,項(xiàng)目中都會(huì)給出 format.xml 文件,如 hadoop(hadoop-format.xml) / druid(druid_intellij_formatting.xml) etc.
換行符
Auto CRLF
# 提交時(shí)轉(zhuǎn)換為 LF,檢出時(shí)轉(zhuǎn)換為 CRLF
$ git config --global core.autocrlf true
# 提交時(shí)轉(zhuǎn)換為 LF,檢出時(shí)不轉(zhuǎn)換
$ git config --global core.autocrlf input
# 提交檢出均不轉(zhuǎn)換
$ git config --global core.autocrlf false
Safe CRLF
# 拒絕提交包含混合換行符的文件
$ git config --global core.safecrlf true
# 允許提交包含混合換行符的文件
$ git config --global core.safecrlf false
# 提交包含混合換行符的文件時(shí)給出警告
$ git config --global core.safecrlf warn
整合持續(xù)集成
Travis
.travis.yml
language:
- java
- scala
- python
- groovy
os:
- windows
jdk:
- oraclejdk8
scala:
- 2.11.8
python:
- 2.7.12
groovy:
- 2.3.11
before_install: sudo echo "MAVEN_OPTS='-Xmx2048m -Xms1024m -Dorg.slf4j.simpleLogger.defaultLogLevel=error'" > ~/.mavenrc
script:
- mvn clean install -B && mvn clean -B
env:
global:
- MAVEN_OPTS: "-Xmx2048m -Xms1024m -Dorg.slf4j.simpleLogger.defaultLogLevel=error"
sudo: required
cache:
directories:
- $HOME/.m2
效果圖
[](https://travis-ci.org/asdf2014/yuzhouwan)
設(shè)置編輯器
在 Mac 下設(shè)置 sublime 作為編輯器
# 修改 git 配置文件
$ vim ~/.gitconfig
[core]
editor = /Applications/Sublime\\ Text.app/Contents/SharedSupport/bin/subl -n -w
# 或者通過命令行配置
$ git config --global core.editor "/Applications/Sublime\ Text.app/Contents/SharedSupport/bin/subl -n -w"
英文縮寫
| 縮寫 | 全拼 | 含義 |
|---|---|---|
| AKA | Also Known As | 也稱作 |
| BTW | By The Way | 順便一提 |
| FWIW | For What It′s Worth | 無(wú)論如何 |
| FWIAW | For What It′s All Worth | 不管有沒有用(FWIW 含義一樣,且 FWIW 更常用一些) |
| FYI | For Your Information | 供你參考 |
| IMHO | In My Humble Opinion | 以我淺見 |
| IMO | In My Opinion | 我的想法是 |
| LGTM | Looks Good to Me | 在我看來(lái)很好 |
| OTOH | On The Other Hand | 另一方面 |
| PTAL | Please Take a Look | 請(qǐng)看一下 |
| TBH | To Be Honest | 老實(shí)說 |
- 本文作者: Benedict Jin
- 本文鏈接: https://yuzhouwan.com/posts/30041/
- 版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-ND 許可協(xié)議。轉(zhuǎn)載請(qǐng)注明出處!