diff --git a/.gitignore b/.gitignore index 09719c9928d9e71143f57bc42501c7b922ab795b..56cd54a7614544e030a65aaa5cf6f84f26a5c288 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /*.iml # Build +dist/ .vscode node_modules __MACOSX @@ -11,3 +12,4 @@ __MACOSX # Other tmp +vuepress diff --git a/src/.vuepress/config.js b/src/.vuepress/config.js index e800d3b3cbe37de7026afb298a36c438e712cde9..9eee8d9c969cbb124e821acebad570f779983ffd 100644 --- a/src/.vuepress/config.js +++ b/src/.vuepress/config.js @@ -24,7 +24,7 @@ module.exports = config({ logo: '/logo.svg', darkmode: 'switch', baseLang: 'zh-CN', - hostname: 'https://gitee.com/gitee-community/opensource-guide', + hostname: 'https://getiot.tech', searchMaxSuggestions: 10, themeColor: { green: '#4fad54', @@ -215,7 +215,7 @@ module.exports = config({ '轻编程与CRMEB打通版的故事', 'DolphinScheduler如何带领我走进开源的世界', '“我的一剂良药”之开源指北', - '要懂得舍得的UMS与JPA的故事', + '要懂得舍得的UMS与JAP的故事', '开源有魔力-DolphinScheduler和我的开源历程', '感谢Apache DolphinScheduler,让我的青春永不褪色', '向微软官方贡献 @types 包', diff --git a/src/.vuepress/public/images/0zDLhAAol8mL2LZY.png b/src/.vuepress/public/images/0zDLhAAol8mL2LZY.png deleted file mode 100644 index 88320562b1d3b6f2ec257068e89473dbef0f5841..0000000000000000000000000000000000000000 Binary files a/src/.vuepress/public/images/0zDLhAAol8mL2LZY.png and /dev/null differ diff --git a/src/.vuepress/public/images/XKGh3Bn7aiEFiwfn.png b/src/.vuepress/public/images/XKGh3Bn7aiEFiwfn.png deleted file mode 100644 index 2a6d6889cbb1752c03f158e9878df1564899c03b..0000000000000000000000000000000000000000 Binary files a/src/.vuepress/public/images/XKGh3Bn7aiEFiwfn.png and /dev/null differ diff --git a/src/.vuepress/public/images/kpKyyRgJ7Zrh2nb4.png b/src/.vuepress/public/images/kpKyyRgJ7Zrh2nb4.png deleted file mode 100644 index 636e37d59330eb4f7725be1baa69e4b2d84e038e..0000000000000000000000000000000000000000 Binary files a/src/.vuepress/public/images/kpKyyRgJ7Zrh2nb4.png and /dev/null differ diff --git "a/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/Git \347\232\204\345\205\245\351\227\250\344\275\277\347\224\250.md" "b/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/Git \347\232\204\345\205\245\351\227\250\344\275\277\347\224\250.md" index 8ae7eef682ad385e4f177b06c45fbe3fa3e51d3f..736fa1d91f24eda35704040c739d52cae33a3006 100644 --- "a/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/Git \347\232\204\345\205\245\351\227\250\344\275\277\347\224\250.md" +++ "b/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/Git \347\232\204\345\205\245\351\227\250\344\275\277\347\224\250.md" @@ -9,7 +9,7 @@ permalink: /git-tutorial/quick-start ### 用户信息 -使用以下命令来让 Git 记住你是谁,以后每次提交都会以此为签名让其他人知道是你做出了贡献 +使用以下命令来让 Git 记住你是谁,以后每次提交都会以此为签名让其他人知道是你做出了贡献。 ```shell git config --global user.name "<你的名字>" @@ -18,218 +18,250 @@ git config --global user.email <你的邮箱> ### init:创建本地仓库 -假设我们将启动一个全新的项目,代码将存在于 `/home/gitee/firstProject`目录,那么以此目录为目标建立仓库 +假设我们将启动一个全新的项目,代码将存在于 `/home/gitee/firstProject` 目录,那么以此目录为目标建立仓库。 ```shell cd /home/gitee/firstProject git init ``` -如此便将仓库建立好了 + +如此便将仓库建立好了。 + ### clone:获取远程仓库 -假设我们要对一个已经存在于远程仓库的项目进行`https://gitee.com/giteeeer/example.git`,那么就需要将其同步到本地的当前目录下 +假设我们要对一个已经存在于远程仓库的项目进行`https://gitee.com/giteeeer/example.git`,那么就需要将其同步到本地的当前目录下。 ```shell git clone https://gitee.com/giteeeer/example.git ``` -注:这样仅仅是将默认分支同步到了本地 -### remote :远程仓库 +注:这样仅仅是将默认分支同步到了本地。 + +### remote:远程仓库 -可以使用以下命令来获取远程仓库地址 +可以使用以下命令来获取远程仓库地址: ```shell git remote -v ``` -由此可以获得两个地址,一个是 fetch,一个是 push,fetch 地址意指我们获取代码的地址,push 则指我们要提交的地址。如下图 + +由此可以获得两个地址,一个是 fetch,一个是 push。fetch 地址意指我们获取代码的地址,push 则指我们要提交的地址,如下图所示。 ![图片](./../../.vuepress/public/images/r88kuUJ1z4lW9go5.png) -### branch :分支管理操作 +### branch:分支管理操作 -用以下命令来获取 branch 列表以便进一步让我们选定需要的分支 +用以下命令来获取 branch 列表以便进一步让我们选定需要的分支: ```shell git branch ``` + ![图片](./../../.vuepress/public/images/NuA3srhhQ1fNClRz.png) 接下来我们将在默认分支(master)上进行操作。 -### add: 让 Git 跟踪变更 +### add:让 Git 跟踪变更 -在本地有了仓库之后,我们可以开始做一些开发工作了,假设我们写了一个“ToAdd.txt”文件 +在本地有了仓库之后,我们可以开始做一些开发工作了,假设我们写了一个 *ToAdd.txt* 文件。 -而这个新增的“ToAdd.txt”是没有被 Git “注意到“的,因此,首先要让 Git 对变更进行追踪,而已经被 Git 跟踪到的文件则是在上一次版本快照中有记录的文件。就好像学生首先要注册学籍,这样学校才能把学生的学习记录放入学籍,而 Git 就是对“学籍”进行管理的人员,入籍这个动作即为`add`。 +而这个新增的 *ToAdd.txt* 是没有被 Git “注意到”的,因此,首先要让 Git 对变更进行追踪,而已经被 Git 跟踪到的文件则是在上一次版本快照中有记录的文件。就好像学生首先要注册学籍,这样学校才能把学生的学习记录放入学籍,而 Git 就是对“学籍”进行管理的人员,入籍这个动作即为 `add`。 -使用以下命令 +使用以下命令: ```shell git add ToAdd.txt ``` -则 Git 会将“ToAdd.txt”文件存入暂存区以实现跟踪。 -在对某些文件进行了改动之后(此处我们修改了 project.txt 文件的内容,增加了 ToAdd.txt 文件),对于 Git 有记录的文件,Git 可以计算出变动并标记为已修改文件,而没有记录的则需要将有需要的文件加入暂存区以便管理,这时候使用`status`命令即可获得文件的状态 + +则 Git 会将 *ToAdd.txt* 文件存入暂存区以实现跟踪。 + +在对某些文件进行了改动之后(此处我们修改了 project.txt 文件的内容,增加了 ToAdd.txt 文件),对于 Git 有记录的文件,Git 可以计算出变动并标记为已修改文件,而没有记录的则需要将有需要的文件加入暂存区以便管理,这时候使用 `status` 命令即可获得文件的状态。 ```shell git status ``` + ![图片](./../../.vuepress/public/images/EoCka30vAARNH789.png) -如上图所示,其中“ToAdd.txt”就是新加入暂存区的文件,“project.txt”就是已经存入暂存区并且 Git 发现有修改的文件,而下面“Untracked files”就是 Git 还没有追踪的文件。 +如上图所示,其中 ToAdd.txt 就是新加入暂存区的文件,project.txt 就是已经存入暂存区并且 Git 发现有修改的文件,而下面 Untracked files 就是 Git 还没有追踪的文件。 -而当我们针对下面 “RemoteSystemTempFiles” 文件夹使用`add`命令之后, +而当我们针对下面 *RemoteSystemTempFiles* 文件夹使用 `add` 命令之后,Git 将此文件夹下所有文件存入暂存区开始追踪。 ```shell git add RemoteSystemTempFiles/ ``` -Git 将此文件夹下所有文件存入暂存区开始追踪,再运行`status`命令得到下图 + +再运行 `git status` 命令得到下图所示信息: ![图片](./../../.vuepress/public/images/YUx3GU6IpSDKUKoM.png) -这时候,“RemoteSystemTempFiles”中的“.project”文件就被纳入暂存区追踪了,而“Untracked files”中就看不到它了。 +这时候,RemoteSystemTempFiles 中的 .project 文件就被纳入暂存区追踪了,而 Untracked files 中就看不到它了。 -要注意的是,刚刚虽然我们是针对“RemoteSystemTempFiles”文件夹进行的`add`操作,纳入暂存区的也仅仅是彼时存在于文件夹中的文件,而如果我们之后再在“RemoteSystemTempFiles"文件夹内增加文件,则仍需针对文件运行`add`命令,否则我们会看到新加入的文件没有被追踪到,正如下图的“ThisOneHasNotBeenTracked.txt”文件。 +要注意的是,刚刚虽然我们是针对 RemoteSystemTempFiles 文件夹进行的 `add` 操作,纳入暂存区的也仅仅是彼时存在于文件夹中的文件,而如果我们之后再在 RemoteSystemTempFiles 文件夹内增加文件,则仍需针对文件运行 `add` 命令,否则我们会看到新加入的文件没有被追踪到,正如下图的 ThisOneHasNotBeenTracked.txt 文件。 ![图片](./../../.vuepress/public/images/5xAArdS8XNcUfXgN.png) ### gitignore:忽略文件 -在上面我们看到了一些与我们项目本身毫无关系的文件比如“git”,“.DS_Store”和“.gitignore”等等,在实际应用中我们会希望这些文件不要出现在 Git 提示当中干扰我们的工作,我们可以编辑“gitignore”文件来让 Git 彻底忽略它们的存在,如将 “git” 甚至“.gitignore”文件的文件名本身写入“gitignore”,那么 Git 就不会再提示我们有关这个是不是被追踪的问题了 +在上面我们看到了一些与我们项目本身毫无关系的文件比如 “git”,“.DS_Store” 和 “.gitignore” 等等,在实际应用中我们会希望这些文件不要出现在 Git 提示当中干扰我们的工作,我们可以编辑 *.gitignore* 文件来让 Git 彻底忽略它们的存在,如将 “git” 甚至 “.gitignore” 文件的文件名本身写入 *.gitignore*,那么 Git 就不会再提示我们有关这个是不是被追踪的问题了。 ![图片](./../../.vuepress/public/images/ZFMVMSUHIgW24k4Y.png) -再运行`status`命令就不会看到针对“git”和“.gitignore”的提示了 +再运行 `status` 命令就不会看到针对 “git” 和 “.gitignore” 的提示了。 ![图片](./../../.vuepress/public/images/jCEIaocNNAdNWlMm.png) -### Fetch 和 Pull : 拉取操作 +### Fetch 和 Pull:拉取操作 -在我们对本地文件进行编辑的同时可能会有其他人也在对项目做出贡献,这就会造成本地和远程仓库的不同步,这时候通过使用`fetch`或`pull`操作访问远程仓库,将本地没有的数据全部拉取到本地 +在我们对本地文件进行编辑的同时可能会有其他人也在对项目做出贡献,这就会造成本地和远程仓库的不同步,这时候通过使用 `fetch` 或 `pull` 操作访问远程仓库,将本地没有的数据全部拉取到本地。 ```shell git pull ``` -这个命令会将远程仓库的变动同步到本地并且自动尝试合并到当前所在的分支,因此可能需要进一步处理冲突才能完成整个`pull`操作。 + +这个命令会将远程仓库的变动同步到本地并且自动尝试合并到当前所在的分支,因此可能需要进一步处理冲突才能完成整个 `pull` 操作。 + ```shell git fetch ``` -要注意的是它和`pull`命令不同,它不会自动合并或修改你当前的变更而你必须在准备好以后手动地进行合并。 +要注意的是它和 `pull` 命令不同,它不会自动合并或修改你当前的变更而你必须在准备好以后手动地进行合并。 + ### diff:对比不同 -通过使用`diff`命令可以让我们详细对比每个被追踪的文件的变更 +通过使用 `diff` 命令可以让我们详细对比每个被追踪的文件的变更。 ```shell git diff ``` -可以看到详细的变动对比 + +可以看到详细的变动对比,如下图所示。 ![图片](./../../.vuepress/public/images/7HfoDCit9E9N3c7E.png) -其中红色表明是删除对应`-`,绿色 表明是增加的部分对应`+`。 +其中红色表明是删除对应 `-`,绿色表明是增加的部分对应 `+`。 -### commit: 提交到本地存储库 +### commit:提交到本地存储库 -光让文件呆在暂存区不是我们的目的,将所有变更写入远程代码仓库才是,所以下一步我们要提交变更。提交的同时记得写一句简明的话来说明本次提交的目的,内容等,参数为`-m`所以 使用以下命令会将所有文件有变动的文件提交到存储库 +光让文件待在暂存区不是我们的目的,将所有变更写入远程代码仓库才是,所以下一步我们要提交变更。提交的同时记得写一句简明的话来说明本次提交的目的,内容等,参数为 `-m`。可以使用以下命令会将所有文件有变动的文件提交到存储库: ```shell git commit -m "修改介绍" ``` -这样就将修改提交了,然后 Git 会反馈一个报告,告诉你提交到了哪个分支,本次变更的 SHA-1 校验和是什么(74219eb),有多少文件被修改过,多少行被添加,多少行被删除。 + +这样就将修改提交了,然后 Git 会反馈一个报告,告诉你提交到了哪个分支,本次变更的 SHA-1 校验和是什么(74219eb),有多少文件被修改过,多少行被添加,多少行被删除。 ![图片](./../../.vuepress/public/images/BV5S2wofGhUsPJMb.png) #### -a:全提交 -每次都先`add`然后再`commit`多少有些繁琐,所以可以使用`-a`参数来将所有变更直接提交而不用使用`add`命令, 即 +每次都先 `add` 然后再 `commit` 多少有些繁琐,所以可以使用 `-a` 参数来将所有变更直接提交而不用使用 `add` 命令, 即: ```shell git commit -a -m "修改介绍" +# 等效于 +git commit -am "修改介绍" ``` -但要小心,这样可能会把不想提交的文件也给提交了,最好和 gitignore 文件配置一起配合使用。 -#### --amend:重新提交 -有时候我们会误操作在某次提交中少提交了某些文件,除了直接再提交一次,我们可以使用 +但要小心,这样可能会把不想提交的文件也给提交了,最好和 .gitignore 文件配置一起配合使用。 + +#### --amend:重新提交 -`--amend`参数来补齐遗漏的文件,如下操作 +有时候我们会误操作在某次提交中少提交了某些文件,除了直接再提交一次,我们可以使用 `--amend` 参数来补齐遗漏的文件。操作如下: ```shell git commit -m “修改介绍” git add renamed.txt git commit --amend ``` -这样就只有一条说明为“修改介绍”的提交被记录下来,第二次提交的内容会**覆盖**第一次的提交。即使用`log`命令的 时候显示记录只有一条有关“修改介绍”。 + +这样就只有一条说明为“修改介绍”的提交被记录下来,第二次提交的内容会**覆盖**第一次的提交。即使用 `log` 命令的时候显示记录只有一条有关“修改介绍”。 + ### rm:移除文件 -Git 可以移除某个文件,我们以“ToRemove.txt”为例,那么可以通过`rm`命令 来实现 +Git 可以移除某个文件,我们以 *ToRemove.txt* 为例,那么可以通过 `rm` 命令来实现。 ```shell rm ToRemove.txt ``` -这样就从文件系统中删除了,接下来让 Git 记录此次操作 + +这样就从文件系统中删除了,接下来让 Git 记录此次操作: + ```shell git rm ToRemove.txt ``` -如果该文件已经放入了暂存区,那么需要加入`-f`参数 来强制移除,这个参数可以认作是 Git 防止误删操作而加的保险 + +如果该文件已经放入了暂存区,那么需要加入 `-f` 参数来强制移除,这个参数可以认作是 Git 防止误删操作而加的保险。 + ```shell git rm -f ToRemove.txt ``` -另一种情况可能更加常用,即我们仅仅是想将其从暂存区移除而不希望把它从磁盘上删除,那么可以加入`--cached`参数来实现 + +另一种情况可能更加常用,即我们仅仅是想将其从暂存区移除而不希望把它从磁盘上删除,那么可以加入 `--cached` 参数来实现: + ```shell git rm --cache ToRemove.txt ``` -那么“ToRemove.txt”会再次回到“Untracked files”列表中并且也会保留在磁盘上。 + +那么 ToRemove.txt 会再次回到 Untracked files 列表中并且也会保留在磁盘上。 ![图片](./../../.vuepress/public/images/GbIhqyecsy6SyY5P.png) -### mv: 移动/重命名文件 +### mv:移动/重命名文件 -在 Git 中,`mv`操作相当于在暂存区删除原文件再添加改名后的文件,也就是先`rm`再`add`,虽然使用者可以同样使用`rm`和`add`命令来达到一样的效果,直接使用`mv`命令无疑更为方便。 +在 Git 中,`mv` 操作相当于在暂存区删除原文件再添加改名后的文件,也就是先 `rm` 再 `add`,虽然使用者可以同样使用 `rm` 和 `add` 命令来达到一样的效果,直接使用 `mv` 命令无疑更为方便。 ```shell git mv ToRemove.txt renamed.txt ``` -当然使用这命令的前提是原文件已经被 Git 追踪 -再运行`status`命令之后,“ToRemove.txt”就被改成了“renamed.txt” + +当然使用这命令的前提是原文件已经被 Git 追踪。 + +再运行 `status` 命令之后,ToRemove.txt 就被改成了 renamed.txt,如下图所示。 ![图片](./../../.vuepress/public/images/U4miY2EtGP5a0as2.png) ### reset HEAD:取消暂存的文件 -当我们希望取消某一个文件的暂存的时候,以“toUntracked.txt”为例,是我们刚刚加入暂存区的文件。 +当我们希望取消某一个文件的暂存的时候,以 *toUntracked.txt* 为例,是我们刚刚加入暂存区的文件。 ![图片](./../../.vuepress/public/images/FxjqroGUQ4x1Hmvh.png) -则可以使用以下命令 +则可以使用以下命令: ```shell git reset HEAD toUntracked.txt ``` -我们会得到一个反馈说 reset 之后剩下的暂存的变动如 + +我们会得到一个反馈说 reset 之后剩下的暂存的变动,如: ![图片](./../../.vuepress/public/images/AlRNI0ej38RIoINw.png) -这里就只剩下了对“project.txt”的修改,运行`status`命令发现`toUntracked.txt`出现在了“Untracked files”列表当中。 +这里就只剩下了对 project.txt 的修改,运行 `status` 命令发现 toUntracked.txt 出现在了 Untracked files 列表当中。 ### checkout:还原 -如果不想保留对文件的修改呢,可以使用`checkout`命令来使其还原到上次提交的样子 +如果不想保留对文件的修改呢,可以使用 `checkout` 命令来使其还原到上次提交的样子。 ```shell git checkout -- project.txt ``` + 注意:这个命令会使 Git 用最新提交的版本覆盖指定的文件,对该文件在本地的所有修改都会消失。 -再运行`status`命令发现针对“project.txt”的修改已经不存在了 + +再运行 `status` 命令发现针对 project.txt 的修改已经不存在了。 ![图片](./../../.vuepress/public/images/aCWIQtjkCZJHE2Qw.png) ### log:查看提交历史 -我们在很多场景下可能会需要查看提交历史,那么使用以下命令 +我们在很多场景下可能会需要查看提交历史,那么使用以下命令: ```shell git log ``` + 此命令会按时间倒叙显示所有提交,包括 SHA-1 校验和、作者名字、邮件地址、时间和提交说明。 + ### push:提交到远程仓库 只存在本地的代码仓库接下来使用以下命令来将本地存储库中的变动同步到远程仓库,这一步你需要提供在 Gitee 的用户名和密码以获取 push 权限。 @@ -237,8 +269,10 @@ git log ```shell git push ``` + ![图片](./../../.vuepress/public/images/qdbRn12Bw6FkOjXi.png) ### 小结 -以上我们介绍了一些最常用的 Git 命令,但实际上 Git 最基本的流程就是`init` /`clone`->`add`->`commit`->`push`,当然在实际使用中因为可能是多人协作,所以我们需要使用分支来支持更为科学的开发策略以提高效率降低成本,与 IDE 整合以提高易用性以及与 DevOps 工具相结合以提高团队的吞吐量等,这些我们将在后面的教程中详细说明。 +以上我们介绍了一些最常用的 Git 命令,但实际上 Git 最基本的流程就是 `init` /`clone`->`add`->`commit`->`push`,当然在实际使用中因为可能是多人协作,所以我们需要使用分支来支持更为科学的开发策略以提高效率降低成本,与 IDE 整合以提高易用性以及与 DevOps 工具相结合以提高团队的吞吐量等,这些我们将在后面的教程中详细说明。 + diff --git "a/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\344\273\200\344\271\210\346\230\257\347\211\210\346\234\254\346\216\247\345\210\266\345\222\214 Git.md" "b/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\344\273\200\344\271\210\346\230\257\347\211\210\346\234\254\346\216\247\345\210\266\345\222\214 Git.md" index bd43743ce30fe26a1a2cf9262384e7a9c0b3a35a..78fb62bae90571df6b9e781e07b3936f43b94580 100644 --- "a/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\344\273\200\344\271\210\346\230\257\347\211\210\346\234\254\346\216\247\345\210\266\345\222\214 Git.md" +++ "b/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\344\273\200\344\271\210\346\230\257\347\211\210\346\234\254\346\216\247\345\210\266\345\222\214 Git.md" @@ -3,41 +3,41 @@ title: 什么是版本控制和 Git permalink: /git-tutorial/what-is-git --- -## 什么是版本控制和 Git -### 关于版本控制 + +## 关于版本控制 你一定不想看到如下图的场景,不但难以确认每一版的改动,还难以找到最需要的版本。 ![图片](./../../.vuepress/public/images/uQyoTPlLtpJme36w.png) -那么这也就是我们做版本控制的原因了:追溯每个变更并管理每个版本,当然此外还需要有更好的协作模式。 +那么这也就是我们做版本控制的原因 —— 追溯每个变更并管理每个版本,当然此外还需要有更好的协作模式。 -### 主流的版本控制系统 +## 主流的版本控制系统 -主流的版本控制系统有 CVS,SVN 和 Git 等 +主流的版本控制系统有 CVS、SVN 和 Git 等。 -#### CVS +### CVS 我们先说 CVS(Concurrent Versions System),它是集中式版本控制系统的典型。它的工作是 C/S 模式的,即在服务器上建立一个仓库,仓库管理员管理这仓库里面的所有文件,任何人需要进行修改的时候需要下载到本地(copy)再进行对文件的修改(modify),改完以后再提交给 CVS,由 CVS 源码库统一进行合并(merge),这样就做到了只有一个人对仓库的文件进行写入,避免了很多冲突和管理难题。 CVS 的痛点很多,比如不支持重命名,只能删除再添加文件。又如每次提交不是原子性的,而是针对单个文件的,这给文件管理带来了极大的灵活性,但同时也对版本控制带来了挑战,想象一下某一个修改了上千个文件的版本上线之后需要回滚,那么管理员就只能一个文件一个文件地来做了。 -#### SVN +### SVN 类似于 CVS ,SVN(subversion)也是集中式版本控制系统,它解决了一些 CVS 的痛点,如支持了重命名,对不同编码的文件的支持等,保证安全性的同时易于管理。同时也将变更变成了原子性的,以一定的灵活性的代价换来了管理的便利。但也因为它是集中控制系统,几乎所有的操作都需要发生在服务器上如对比,提交,还原等,就给服务器带来了压力,如此就不适合进行开源项目而只适合开发人数有限的项目的开发。同样的,开发人员每天都需要从服务器上获取最新的文件随后进行修改,解决冲突并提交,在某些不能保证稳定网络连接的情况下SVN是没有办法帮助企业保证其业务的连续性的。 -#### Git +### Git -作为本文的主角, Git 是这些主流版本控制工具中唯一的分布式版本控制系统,开发者可以将整个代码库放到本地,这样不要求客户端时刻联网而就可以在本地进行对比、提交等工作,然后再`push`进服务器端进行`merge`即可。将部分工作放在本地以平衡服务器的负载,这样的解决方案使得 Git 支持大规模多用户的开发模式便可更好地支持开源项目。 +作为本文的主角,Git 是这些主流版本控制工具中唯一的分布式版本控制系统,开发者可以将整个代码库放到本地,这样不要求客户端时刻联网而就可以在本地进行对比、提交等工作,然后再 `push` 进服务器端进行 `merge` 即可。将部分工作放在本地以平衡服务器的负载,这样的解决方案使得 Git 支持大规模多用户的开发模式便可更好地支持开源项目。 ## Git 简史 同生活中的许多伟大事物一样,Git 诞生于一个极富纷争大举创新的年代。 -Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。 到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。 +Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,整个项目组开始启用一个专有的分布式版本控制系统 BitKeeper 来管理和维护代码。 -到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。 这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。他们对新的系统制订了若干目标: +到了 2005 年,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了 Linux 内核社区免费使用 BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds)基于使用 BitKeeper 时的经验教训,开发出自己的版本系统。他们对新的系统制订了若干目标: * 速度 * 简单的设计 @@ -45,8 +45,6 @@ Linux 内核开源项目有着为数众多的参与者。 绝大多数的 Linux * 完全分布式 * 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量) -自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统 - -注:本段引用自 +自诞生于 2005 年以来,Git 日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统。 -[https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-Git-%E7%AE%80%E5%8F%B2](https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-Git-%E7%AE%80%E5%8F%B2) +注:本段引用自 [https://git-scm.com/book/zh/v2/起步-Git-简史](https://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-Git-%E7%AE%80%E5%8F%B2)。 diff --git "a/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\345\246\202\344\275\225\345\256\211\350\243\205 Git.md" "b/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\345\246\202\344\275\225\345\256\211\350\243\205 Git.md" index ac4648955c38341c37d3898988e5c48f9a92df28..918c73668d1cbd7b1aa65d0c9f76b1115c46e812 100644 --- "a/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\345\246\202\344\275\225\345\256\211\350\243\205 Git.md" +++ "b/src/git_tutorial/Git \345\205\245\351\227\250\357\274\210\345\210\235\347\272\247\347\257\207\357\274\211/\345\246\202\344\275\225\345\256\211\350\243\205 Git.md" @@ -3,34 +3,41 @@ title: 如何安装 Git language: zh_CN permalink: /git-tutorial/how-to-install-git --- + + ## 根据系统安装 ### 在 Windows 下安装 -打开 [https://git-scm.com/download/win](https://git-scm.com/download/win),下载会自动开始,运行下载的可执行文件跟随指引安装 +打开 [https://git-scm.com/download/win](https://git-scm.com/download/win),下载会自动开始,运行下载的可执行文件跟随指引安装。 ### 在 Linux 下安装 #### Debian/Ubuntu -用以下命令来安装最新的发布版 Git +用以下命令来安装最新的发布版 Git: +```bash +$ sudo apt-get install git ``` -apt-get install git -``` -Ubuntu 系统还可使用以下命令来安装最新的稳定 Upstream 版 Git -``` -add-apt-repository ppa:git-core/ppa -apt update; apt install git + +Ubuntu 系统还可使用以下命令来安装最新的稳定 Upstream 版 Git: + +```bash +$ sudo add-apt-repository ppa:git-core/ppa +$ sudo apt update; apt install git ``` + #### RedHat 企业版 Linux,Oracle Linux 等 -RHEL 和其他衍生版本可使用`dnf`命令来安装 +RHEL 和其他衍生版本可使用 `dnf` 命令来安装: +```bash +$ sudo dnf install git-all ``` -sudo dnf install git-all -``` -你也可以从 [https://mirrors.edge.kernel.org/pub/software/scm/git/](https://mirrors.edge.kernel.org/pub/software/scm/git/) 下载源码来编译安装最新版的 Git 。 + +你也可以从 [https://mirrors.edge.kernel.org/pub/software/scm/git/](https://mirrors.edge.kernel.org/pub/software/scm/git/) 下载源码来编译安装最新版的 Git 。 + #### 更多参见 [https://git-scm.com/download/linux](https://git-scm.com/download/linux) @@ -39,25 +46,25 @@ sudo dnf install git-all #### homebrew -如果你安装了 homebrew,可以通过以下命令来安装 +如果你安装了 homebrew,可以通过以下命令来安装: -```shell +```bash $ brew install git ``` + #### 安装包安装 -从 [https://sourceforge.net/projects/git-osx-installer/](https://sourceforge.net/projects/git-osx-installer/) 下载后根据提示安装 +从 [https://sourceforge.net/projects/git-osx-installer/](https://sourceforge.net/projects/git-osx-installer/) 下载后根据提示安装。 #### 编译源码 -从 [https://mirrors.edge.kernel.org/pub/software/scm/git/](https://mirrors.edge.kernel.org/pub/software/scm/git/) 下载源代码后进行编译 - +从 [https://mirrors.edge.kernel.org/pub/software/scm/git/](https://mirrors.edge.kernel.org/pub/software/scm/git/) 下载源代码后进行编译。 ## Git 工具 ### 命令行工具 - Git 作为开源版本控制工具有诸多的用法,可以使用原生的命令行、图形界面以及第三方提供的图形界面工具,这其中命令行工具是最基础也是最强大的。 +Git 作为开源版本控制工具有诸多的用法,可以使用原生的命令行、图形界面以及第三方提供的图形界面工具,这其中命令行工具是最基础也是最强大的。 在上文中我们就使用的是在 MacOS 中的命令行工具 Terminal。当然如果你用的是 Linux 系统,也可以用 Terminal ,如果你用的是 Windows 系统那么可以用命令窗口(Command Prompt)或者 PowerShell。 @@ -69,11 +76,11 @@ Source Tree 是 Atlassian 公司出品的可运行在 Mac 和 Windows 下的 Git ![图片](./../../.vuepress/public/images/lbk1YLUGKVvPDZkE.png) -图片来源:[https://www.sourcetreeapp.com/](https://www.sourcetreeapp.com/) +> 图片来源:[https://www.sourcetreeapp.com](https://www.sourcetreeapp.com) #### Tortoise Git -如果你在用 Windows ,那么可以考虑从 [https://tortoisegit.org/download/](https://tortoisegit.org/download/)下载使用Tortoise Git +如果你在用 Windows ,那么可以考虑从 [https://tortoisegit.org/download/](https://tortoisegit.org/download/) 下载使用 Tortoise Git。 ### Git 集成 IDE 客户端 @@ -81,7 +88,7 @@ IDE 集成 Git 给我们提供了一站式的解决方案,在不切换程序 #### Xcode -Xcode 自带 Git,可以在欢迎界面执行`clone`操作即可 +Xcode 自带 Git,可以在欢迎界面选择 `clone` 操作即可。 ![图片](./../../.vuepress/public/images/WXDktOKkcZRBC4f4.png) @@ -89,8 +96,7 @@ Xcode 自带 Git,可以在欢迎界面执行`clone`操作即可 #### VS Code -同样的 VS Code 也集成了 Git,可以通过设置来进行配置,之后即可在主界面使用 Git - +同样的 VS Code 也集成了 Git,可以通过设置来进行配置,之后即可在主界面使用 Git。 ![图片](./../../.vuepress/public/images/wpIFspkDtaE3ML2m.png) @@ -102,10 +108,10 @@ Xcode 自带 Git,可以在欢迎界面执行`clone`操作即可 #### JetBrains 系列 -JetBrains 提供了针对多种语言的开发工具,配置方法大同小异,我们以 IntelliJ IDEA 社区版为例: +JetBrains 提供了针对多种语言的开发工具,配置方法大同小异,我们以 IntelliJ IDEA 社区版为例进行说明。 默认支持 SVN,Git 等版本控制工具,在设置中可以进行设置。 ![图片](./../../.vuepress/public/images/qUNdkMsWPsGRwrL1.png) -可以在主界面中进行`checkout`、`commit`、`push`等一系列操作: +可以在主界面中进行 `checkout`、`commit`、`push` 等一系列操作。 diff --git "a/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\210\206\346\224\257\344\270\216\345\220\210\345\271\266\347\233\270\345\205\263\345\221\275\344\273\244.md" "b/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\210\206\346\224\257\344\270\216\345\220\210\345\271\266\347\233\270\345\205\263\345\221\275\344\273\244.md" index 83febc0bc84b05dd7833b69a938be51b552da91a..850946ca6c32efa8b0df0334629aa59a61baee85 100644 --- "a/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\210\206\346\224\257\344\270\216\345\220\210\345\271\266\347\233\270\345\205\263\345\221\275\344\273\244.md" +++ "b/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\210\206\346\224\257\344\270\216\345\220\210\345\271\266\347\233\270\345\205\263\345\221\275\344\273\244.md" @@ -3,8 +3,6 @@ title: 分支与合并相关命令 permalink: /git-tutorial/branch-and-merge --- - - ## 分支简介 分支功能是 Git 最为强大的功能之一,我们一直在使用的就是主线分支,就像一根时间轴,每次新提交都建立在上一次的基础上,正是因为这样我们才可以任意改变我们所处的位置,实现在不同时间轴上进行切换。 diff --git "a/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\270\270\347\224\250 Git \345\221\275\344\273\244.md" "b/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\270\270\347\224\250 Git \345\221\275\344\273\244.md" index d5d8b83a1e3caf1056661113b8343c0c6d412db6..6e980ad2a525caad2a6332698399970d784d7d9b 100644 --- "a/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\270\270\347\224\250 Git \345\221\275\344\273\244.md" +++ "b/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\345\270\270\347\224\250 Git \345\221\275\344\273\244.md" @@ -250,6 +250,5 @@ $ git checkout -b v1.1-dev v1.1 引用: -[机智的程序员小熊-Git常用命令](https://coding3min.com/328.html) - -[https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE](https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE) \ No newline at end of file +- [机智的程序员小熊-Git常用命令](https://coding3min.com/328.html) +- [https://git-scm.com/book/zh/v2/Git-基础-打标签](https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE) diff --git "a/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\346\220\255\345\273\272 Git \347\233\270\345\205\263\345\221\275\344\273\244.md" "b/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\346\220\255\345\273\272 Git \347\233\270\345\205\263\345\221\275\344\273\244.md" index 329d4dddde0531164d53cbe2e8100ae1a388bd92..6b439186529890e73d0331342fa13708d46eefc3 100644 --- "a/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\346\220\255\345\273\272 Git \347\233\270\345\205\263\345\221\275\344\273\244.md" +++ "b/src/git_tutorial/Git \345\221\275\344\273\244\350\257\246\350\247\243/\346\220\255\345\273\272 Git \347\233\270\345\205\263\345\221\275\344\273\244.md" @@ -390,5 +390,6 @@ Receiving objects: 100% (3/3), done. 参考 : -* [https://blog.csdn.net/AAA17864308253/article/details/103115291](https://blog.csdn.net/AAA17864308253/article/details/103115291) -* [https://git-scm.com/book/zh/v2/%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E7%9A%84-Git-Smart-HTTP](https://git-scm.com/book/zh/v2/%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E7%9A%84-Git-Smart-HTTP) \ No newline at end of file +* [基于 git+httpd 搭建 http 协议的 git 仓库](https://blog.csdn.net/AAA17864308253/article/details/103115291) +* [https://git-scm.com/book/zh/v2/服务器上的-Git-Smart-HTTP](https://git-scm.com/book/zh/v2/%E6%9C%8D%E5%8A%A1%E5%99%A8%E4%B8%8A%E7%9A%84-Git-Smart-HTTP) + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/1. \344\275\234\344\270\272\345\256\242\346\210\267\347\253\257\347\232\204 Git.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/1. \344\275\234\344\270\272\345\256\242\346\210\267\347\253\257\347\232\204 Git.md" index 2e136978f5e1344d4f80cf293c36063fd1fbd60b..1250d0fc6e8426dd79b2a2aa0a2208e61b7f57ba 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/1. \344\275\234\344\270\272\345\256\242\346\210\267\347\253\257\347\232\204 Git.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/1. \344\275\234\344\270\272\345\256\242\346\210\267\347\253\257\347\232\204 Git.md" @@ -1,26 +1,22 @@ --- -title: 作为客户端的 Git +title: 作为 SVN 客户端的 Git permalink: /git-tutorial/git-and-svn --- ## Git 与 Subversion -### git svn +在 Git 中所有 Subversion 桥接命令的基础命令是 `git svn`。 它可以跟很多命令,接下来演示一些最常用的命令。 -在 Git 中所有 Subversion 桥接命令的基础命令是`git svn`。 它可以跟很多命令,接下来演示一些最常用的命令。 +需要特别注意的是当你使用 `git svn` 时,就是在与 Subversion 打交道,一个与 Git 完全不同的系统。 尽管**可以**在本地新建分支与合并分支,但是你最好还是通过变基你的工作来保证你的历史尽可能是直线,并且避免做类似同时与 Git 远程服务器交互的事情。 -需要特别注意的是当你使用`git svn`时,就是在与 Subversion 打交道,一个与 Git 完全不同的系统。 尽管**可以**在本地新建分支与合并分支,但是你最好还是通过变基你的工作来保证你的历史尽可能是直线,并且避免做类似同时与 Git 远程服务器交互的事情。 +### 开始 -**开始** - -我先创建了一个SVN的测试仓库,里面随便塞了几个文件 - -[https://f69j2gkvb3upvz7/svn/mypro4_git_svn](https://f69j2gkvb3upvz7/svn/mypro4_git_svn) +我先创建了一个 SVN 的测试仓库([https://f69j2gkvb3upvz7/svn/mypro4_git_svn](https://f69j2gkvb3upvz7/svn/mypro4_git_svn)),里面随便塞了几个文件。 ![图片](./../../../.vuepress/public/images/h7e2yyZpFrr10TPq.png) -使用`git svn clone`命令即可完成从 svn 仓库拉取到本地, +使用 `git svn clone` 命令即可完成从 svn 仓库拉取到本地: -``` +```shell $ git svn clone https://f69j2gkvb3upvz7/svn/mypro4_git_svn Initialized empty Git repository in G:/git_svn_test/mypro4_git_svn/.git/         A       delete.sql @@ -34,31 +30,35 @@ Checked out HEAD:   https://f69j2gkvb3upvz7/svn/mypro4_git_svn r2 ``` -由于该命令会将 svn 仓库中所有版本的更新都会同步到本地仓库,如果项目更新次数过多会花费很长的时间,所以我们可以通过指定版本号以避免不必要的更新 +由于该命令会将 svn 仓库中所有版本的更新都会同步到本地仓库,如果项目更新次数过多会花费很长的时间,所以我们可以通过指定版本号以避免不必要的更新。 -如:`git svn clone -r2:HEAD [svn_url] [new_name]`,r2为最新的版本号,查看版本号可直接通过浏览器访问svn地址,点击右上角的查看历史即可看到版本号信息, 如下图所示 +如:`git svn clone -r2:HEAD [svn_url] [new_name]`,r2 为最新的版本号,查看版本号可直接通过浏览器访问 svn 地址,点击右上角的查看历史即可看到版本号信息,如下图所示。 ![图片](./../../../.vuepress/public/images/7AVgzuZx5pYxldPs.png) 至此,我们得到了一个已经导入了分支与标签的有效的 Git 仓库: -``` +```shell $ git branch -a * master   remotes/git-svn ``` -**提交回 Subversion** + +### 提交回 Subversion + 现在你有了一个工作目录,你可以在项目上做一些改动,然后高效地使用 Git 作为 SVN 客户端将你的提交推送到上游。 一旦编辑了一个文件并提交它,你就有了一个存在于本地 Git 仓库的提交,这提交在 Subversion 服务器上并不存在: -``` +```shell $ git commit -am 'test commit' [master 7e3b45a] test commit  1 file changed, 1 insertion(+) ``` -你可以离线做几次提交然后一次性将它们推送到 Subversion 服务器。 要推送到一个 Subversion 服务器,运行`git svn dcommit`命令: -``` + +你可以离线做几次提交然后一次性将它们推送到 Subversion 服务器。要推送到一个 Subversion 服务器,运行 `git svn dcommit`命令: + +```shell $ git svn dcommit Committing to https://f69j2gkvb3upvz7/svn/mypro4_git_svn ...         M       delete.sql @@ -68,11 +68,14 @@ r3 = a208b7c1c2adc4132e1b88b4cbf09ba98100746f (refs/remotes/git-svn) No changes between 7e3b45aae35d9ddc336fcc71d3dc56be9860dd3d and refs/remotes/git-svn Resetting to the latest refs/remotes/git-svn ``` + ![图片](./../../../.vuepress/public/images/8xuO2QkKioC5524x.png) -这会拿走你在 Subversion 服务器代码之上所做的所有提交,针对每一个做一个 Subversion 提交,然后重写你本地的 Git 提交来包含一个唯一的标识符。 这很重要因为这意味着所有你的提交的 SHA-1 校验和都改变了。 部分由于这个原因,同时使用一个基于 Git 的项目远程版本和一个 Subversion 服务器并不是一个好主意。 如果你查看最后一次提交,有新的`git-svn-id`被添加: +这会拿走你在 Subversion 服务器代码之上所做的所有提交,针对每一个做一个 Subversion 提交,然后重写你本地的 Git 提交来包含一个唯一的标识符。这很重要因为这意味着所有你的提交的 SHA-1 校验和都改变了。部分由于这个原因,同时使用一个基于 Git 的项目远程版本和一个 Subversion 服务器并不是一个好主意。 -``` +如果你查看最后一次提交,有新的 `git-svn-id` 被添加: + +```shell $ git log -1 commit a208b7c1c2adc4132e1b88b4cbf09ba98100746f (HEAD -> master, git-svn) Author: will @@ -80,10 +83,12 @@ Date:   Sun Sep 20 17:37:41 2020 +0000     test commit     git-svn-id: https://f69j2gkvb3upvz7/svn/mypro4_git_svn@3 7adf1bb6-8b8d-ba41-906b-aa243fc2b489 ``` -**拉取新改动** -如果你和其他开发者一起工作,当在某一时刻你们其中之一推送时,另一人尝试推送修改会导致冲突。 那次修改会被拒绝直到你合并他们的工作。 在`git svn`中,它看起来是这样的: -``` +### 拉取新改动 + +如果你和其他开发者一起工作,当在某一时刻你们其中之一推送时,另一人尝试推送修改会导致冲突。 那次修改会被拒绝直到你合并他们的工作。 在 `git svn` 中,它看起来是这样的: + +```shell $ git commit -am 'test commit 2' [master 55bbeea] test commit 2  1 file changed, 2 insertions(+), 1 deletion(-) @@ -95,8 +100,10 @@ Item is out of date: File '/update.sql' is out of date W: 55bbeea2d8b31d0bc27e4950ef6eab550e3ef21a and refs/remotes/git-svn differ, using rebase: :100644 100644 b0d87c3f73b0ddc69875d6caa5059a2af3b7643e 37034df32709dfcc893f4828be7d023931400086 M      update.sql ``` -为了解决这种情况,可以运行`git svn rebase`,它会从服务器拉取任何你本地还没有的改动,并将你所有的工作变基到服务器的内容之上: -``` + +为了解决这种情况,可以运行 `git svn rebase`,它会从服务器拉取任何你本地还没有的改动,并将你所有的工作变基到服务器的内容之上: + +```shell $ git svn rebase         M       update.sql r4 = 805ae86b6428fc039ec58b500a74406312b7f2fd (refs/remotes/git-svn) @@ -117,8 +124,10 @@ You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort". rebase refs/remotes/git-svn: command returned error: 128 ``` -处理了冲突之后就可以顺利地`dcommit`: -``` + +处理了冲突之后就可以顺利地 `dcommit`: + +```shell $ git svn dcommit Committing to https://f69j2gkvb3upvz7/svn/mypro4_git_svn ...         M       update.sql @@ -128,12 +137,14 @@ r5 = a66548dab43982fbcf05b43cf24abdec46ff930e (refs/remotes/git-svn) No changes between 5e7b5ba362f0a83ec137c7394cb3da9df0b763d3 and refs/remotes/git-svn Resetting to the latest refs/remotes/git-svn ``` -**Git 分支问题** -当适应了 Git 的工作流程,你大概会想要创建主题分支,在上面做一些工作,然后将它们合并入主分支。 如果你正通过`git svn`推送到一个 Subversion 服务器,你可能想要把你的工作变基到一个单独的分支上,而不是将分支合并到一起。 比较喜欢变基的原因是因为 Subversion 有一个线性的历史并且无法像 Git 一样处理合并,所以`git svn`在将快照转换成 Subversion 提交时,只会保留第一父提交。 -假设你的历史像下面这样:创建了一个`experiment`分支,做了两次提交,然后将它们合并回`master`。 当`dcommit`时,你看到输出是这样的: +### Git 分支问题 -``` +当适应了 Git 的工作流程,你大概会想要创建主题分支,在上面做一些工作,然后将它们合并入主分支。如果你正通过 `git svn` 推送到一个 Subversion 服务器,你可能想要把你的工作变基到一个单独的分支上,而不是将分支合并到一起。 比较喜欢变基的原因是因为 Subversion 有一个线性的历史并且无法像 Git 一样处理合并,所以 `git svn` 在将快照转换成 Subversion 提交时,只会保留第一父提交。 + +假设你的历史像下面这样:创建了一个 `experiment` 分支,做了两次提交,然后将它们合并回 `master`。当 `dcommit` 时,你看到输出是这样的: + +```shell $ git svn dcommit Committing to file:///tmp/test-svn/trunk ... M CHANGES.txt @@ -149,30 +160,35 @@ r90 = cb522197870e61467473391799148f6721bcf9a0 (refs/remotes/origin/trunk) No changes between 71af502c214ba13123992338569f4669877f55fd and refs/remotes/origin/trunk Resetting to the latest refs/remotes/origin/trunk ``` -在一个合并过历史提交的分支上`dcommit`命令工作得很好,除了当你查看你的 Git 项目历史时,它并没有重写所有你在`experiment`分支上所做的任意提交——相反,所有这些修改显示一个单独合并提交的 SVN 版本中。 -当其他人克隆那些工作时,他们只会看到一个被塞入了所有改动的合并提交,就像运行了`git merge --squash`;他们无法看到修改从哪来或何时提交的信息。 -**Subversion 分支** +在一个合并过历史提交的分支上 `dcommit` 命令工作得很好,除了当你查看你的 Git 项目历史时,它并没有重写所有你在 `experiment` 分支上所做的任意提交 —— 相反,所有这些修改显示一个单独合并提交的 SVN 版本中。 + +当其他人克隆那些工作时,他们只会看到一个被塞入了所有改动的合并提交,就像运行了 `git merge --squash`;他们无法看到修改从哪来或何时提交的信息。 + +### Subversion 分支 在 Subversion 中新建分支与在 Git 中新建分支并不相同;如果你能不用它,那最好就不要用。 -### Subversion 命令 +## Subversion 命令 -`git svn`工具集通过提供很多功能与 Subversion 中那些相似的命令来帮助简化转移到 Git 的过程。 下面是一些提供了 Subversion 中常用功能的命令。 +`git svn` 工具集通过提供很多功能与 Subversion 中那些相似的命令来帮助简化转移到 Git 的过程。下面是一些提供了 Subversion 中常用功能的命令。 -SVN 风格历史 +### SVN 风格历史 -如果你习惯于使用 Subversion 并且想要看 SVN 输出风格的提交历史,可以运行`git svn log`来查看 SVN 格式的提交历史: +如果你习惯于使用 Subversion 并且想要看 SVN 输出风格的提交历史,可以运行 `git svn log` 来查看 SVN 格式的提交历史: ![图片](./../../../.vuepress/public/images/pCYDbL6EcW1VjALw.png) -关于`git svn log`,有两件重要的事你应该知道。 首先,它是离线工作的,并不像真正的`svn log`命令,会向 Subversion 服务器询问数据。 其次,它只会显示已经提交到 Subversion 服务器上的提交。它更像是最后获取到的 Subversion 服务器上的提交状态。 +关于 `git svn log`,有两件重要的事你应该知道: -SVN 注解 +- 首先,它是离线工作的,并不像真正的 `svn log` 命令,会向 Subversion 服务器询问数据。 +- 其次,它只会显示已经提交到 Subversion 服务器上的提交。它更像是最后获取到的 Subversion 服务器上的提交状态。 -类似`git svn log`命令离线模拟了`svn log`命令,你可以认为`git svn blame [FILE]`离线模拟了`svn annotate`。 输出看起来像这样: +### SVN 注解 -``` +类似 `git svn log` 命令离线模拟了 `svn log` 命令,你可以认为 `git svn blame [FILE]` 离线模拟了 `svn annotate`。输出看起来像这样: + +```shell $ git svn blame update.sql      4       will update table set id='22' where 1=1      5       will version2222 @@ -180,12 +196,14 @@ $ git svn blame update.sql      5       will conflict      5       will test commit 2 ``` + 重复一次,它并不显示你在 Git 中的本地提交,也不显示同一时间被推送到 Subversion 的其他提交。 -SVN 服务器信息 -可以通过运行`git svn info`得到与`svn info`相同种类的信息。 +### SVN 服务器信息 -``` +可以通过运行 `git svn info` 得到与 `svn info` 相同种类的信息。 + +```shell $ git svn info Path: . URL: https://f69j2gkvb3upvz7/svn/mypro4_git_svn @@ -198,14 +216,22 @@ Last Changed Author: will Last Changed Rev: 5 Last Changed Date: 2020-09-21 01:44:41 +0800 (周一, 21 九月 2020) ``` -这就像是在你上一次和 Subversion 服务器通讯时同步了之后,离线运行的`blame`与`log`命令。 -忽略 SUBVERSION 所忽略的 -如果克隆一个在任意一处设置`svn:ignore`属性的 Subversion 仓库时,你也许会想要设置对应的`.gitignore`文件,这样就不会意外的提交那些不该提交的文件。`git svn`有两个命令来帮助解决这个问题。 第一个是`git svn create-ignore`,它会为你自动地创建对应的`.gitignore`文件,这样你的下次提交就能包含它们。 +这就像是在你上一次和 Subversion 服务器通讯时同步了之后,离线运行的 `blame` 与 `log` 命令。 -第二个命令是`git svn show-ignore`,它会将你需要放在`.gitignore`文件中的每行内容打印到标准输出,这样就可以将输出内容重定向到项目的例外文件中: +### 忽略 SVN 所忽略的 -``` +如果克隆一个在任意一处设置 `svn:ignore` 属性的 Subversion 仓库时,你也许会想要设置对应的 `.gitignore` 文件,这样就不会意外的提交那些不该提交的文件。 + +`git svn` 有两个命令来帮助解决这个问题。 + +第一个是 `git svn create-ignore`,它会为你自动地创建对应的 `.gitignore` 文件,这样你的下次提交就能包含它们。 + +第二个命令是 `git svn show-ignore`,它会将你需要放在 `.gitignore` 文件中的每行内容打印到标准输出,这样就可以将输出内容重定向到项目的例外文件中: + +```shell $ git svn show-ignore > .git/info/exclude ``` -这样,你就不会由于`.gitignore`文件而把项目弄乱。 当你是 Subversion 团队中唯一的 Git 用户时这是一个好的选项,并且你的队友并不想要项目内存在`.gitignore`文件。 \ No newline at end of file + +这样,你就不会由于 `.gitignore` 文件而把项目弄乱。当你是 Subversion 团队中唯一的 Git 用户时这是一个好的选项,并且你的队友并不想要项目内存在 `.gitignore` 文件。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/2. \350\277\201\347\247\273\345\210\260 Git.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/2. \350\277\201\347\247\273\345\210\260 Git.md" index 3137ce85b8f6ada9619a9836dbeb6ba11a42efa1..a31f0ec6a9998a2e2f087c6ce7302a6bd67dbf1e 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/2. \350\277\201\347\247\273\345\210\260 Git.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \344\270\216\345\205\266\344\273\226\347\263\273\347\273\237/2. \350\277\201\347\247\273\345\210\260 Git.md" @@ -1,5 +1,5 @@ --- -title: 迁移到 Git +title: 从 SVN 迁移到 Git permalink: /git-tutorial/migrate-svn-to-git --- @@ -9,14 +9,16 @@ permalink: /git-tutorial/migrate-svn-to-git 如果项目体量不大,开发人员不多,简单粗暴点也还好。但是因为当时的那个项目很大,迭代了有几年了,后面有些遗留的生产问题报出来,这时候想找当事人就很难了,因为没有迁移前的代码更新记录了,只有一个提交记录。所以迁移的时候还是要注意方法。 -如果要做这样的大项目迁移工作,而且要带上提交记录,那最好还是要用 git svn 命令。 +如果要做这样的大项目迁移工作,而且要带上提交记录,那最好还是要用 `git svn` 命令。 -## 1.clone项目 +## clone 项目 ```shell  git svn clone https://f69j2gkvb3upvz7/svn/mypro4_git_svn ``` -这样拉下来的项目是带有提交日志等信息的 + +这样拉下来的项目是带有提交日志等信息的。 + ```shell $ git log commit a66548dab43982fbcf05b43cf24abdec46ff930e (HEAD -> master, git-svn) @@ -30,22 +32,28 @@ Date:   Sun Sep 20 17:40:52 2020 +0000     update version2     git-svn-id: https://f69j2gkvb3upvz7/svn/mypro4_git_svn@4 7adf1bb6-8b8d-ba41- 906b-aa243fc2b489 ``` -## 2.添加远程仓库 + +## 添加远程仓库 ```shell git remote add origin https://gitee.com/willcoder/my_svn_git.git ``` -当然这个仓库地址是真实存在的,我是直接在Gitee上建的一个测试。 -如果这一步的时候提示: + +当然这个仓库地址是真实存在的,我是直接在 Gitee 上建的一个测试。 + +如果这一步的时候提示: ```shell fatal: remote origin already exists. ``` + 那就先删除远程仓库再添加。 + ```shell $ git remote rm origin ``` -## 3.推送到远程仓库 + +## 推送到远程仓库 ```shell $ git push https://gitee.com/willcoder/my_svn_git.git @@ -59,9 +67,10 @@ remote: Powered by GITEE.COM [GNK-5.0] To https://gitee.com/willcoder/my_svn_git.git  * [new branch]      master -> master ``` -## 4.验证是否成功 -新建一个文件夹,然后再将远程仓库clone下来 +## 验证是否成功 + +新建一个文件夹,然后再将远程仓库 clone 下来: ```shell $ git clone https://gitee.com/willcoder/my_svn_git.git @@ -72,7 +81,9 @@ remote: Compressing objects: 100% (9/9), done. remote: Total 15 (delta 3), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (15/15), done. ``` -### **git log** + +通过 `git log` 查看记录: + ```shell $ git log commit 55bbeea2d8b31d0bc27e4950ef6eab550e3ef21a (HEAD -> master, origin/master, origin/HEAD) @@ -89,4 +100,5 @@ Author: will Date:   Sun Sep 20 17:28:54 2020 +0000     version2     git-svn-id: https://f69j2gkvb3upvz7/svn/mypro4_git_svn@2 7adf1bb6-8b8d-ba41- -``` \ No newline at end of file +``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/1. \345\272\225\345\261\202\345\221\275\344\273\244\345\222\214\351\253\230\345\261\202\345\221\275\344\273\244.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/1. \345\272\225\345\261\202\345\221\275\344\273\244\345\222\214\351\253\230\345\261\202\345\221\275\344\273\244.md" index 64c2700c3f006d6009e32cd22aa5d399362c0b57..fa4b08299cff14dff82b97ce15a9918a178c5ea5 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/1. \345\272\225\345\261\202\345\221\275\344\273\244\345\222\214\351\253\230\345\261\202\345\221\275\344\273\244.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/1. \345\272\225\345\261\202\345\221\275\344\273\244\345\222\214\351\253\230\345\261\202\345\221\275\344\273\244.md" @@ -2,34 +2,29 @@ title: 底层命令和高层命令 permalink: /git-tutorial/plumbing-and-porcelain --- + 此前已经详述了 Git 的使用和协作,接下来我们一起深入的了解一下它的内部原理和实现方式。 从根本上理解,Git 是 一个内容寻址(content-addressable)文件系统,并在此之上提供了一个版本控制系统的用户界面。 -由于 Git 最初是一套面向版本控制系统的工具集,而不是一个完整的、用户友好的版本控制系统, 所以它还包含了一部分用于完成底层工作的子命令。 这些命令被设计成能以 UNIX 命令行的风格连接在一起,或由脚本调用,来完成工作。 这部分命令一般被称作“底层(plumbing)”命令,而那些更友好的命令,比如 checkout , branch 等则被称作“上层(porcelain)”命令。 +由于 Git 最初是一套面向版本控制系统的工具集,而不是一个完整的、用户友好的版本控制系统, 所以它还包含了一部分用于完成底层工作的子命令。 这些命令被设计成能以 UNIX 命令行的风格连接在一起,或由脚本调用,来完成工作。 这部分命令一般被称作 “底层(plumbing)” 命令,而那些更友好的命令,比如 checkout、branch 等则被称作 “上层(porcelain)” 命令。 -其实目前的上层命令已经足够日常使用,但是底层命令能够让我们了解Git 是如何完成工作的,以及它为何如此运作的,更好的理解Git的工作机制, 多数底层命令并不面向最终用户:它们更适合作为新工具的组件和自定义脚本的组成部分。 +其实目前的上层命令已经足够日常使用,但是底层命令能够让我们了解 Git 是如何完成工作的,以及它为何如此运作的,更好的理解 Git 的工作机制,多数底层命令并不面向最终用户:它们更适合作为新工具的组件和自定义脚本的组成部分。 -当在一个新目录或已有目录执行 git init 时,Git 会创建一个 .git 目录。 这个目录包含了几乎所有 Git 存储和操作的东西。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。 本章探讨的所有内容,均位于这个目录内。 新初始化的 .git 目录的典型结构如下: +当在一个新目录或已有目录执行 `git init` 时,Git 会创建一个 .git 目录。这个目录包含了几乎所有 Git 存储和操作的东西。 如若想备份或复制一个版本库,只需把这个目录拷贝至另一处即可。本章探讨的所有内容,均位于这个目录内。新初始化的 .git 目录的典型结构如下: ![图片](./../../../.vuepress/public/images/yk78PG28OyjpL6CX.png) -随着 Git 版本的不同,该目录下可能还会包含其他内容。 不过对于一个全新的 git init 版本库,这将是你看到的默认结构: - -`description` 文件仅供 GitWeb 程序使用,我们无需关心。 - -`config` 文件包含项目特有的配置选项。 - -`info` 目录包含一个全局性排除(global exclude)文件, 用以放置那些不希望被记录在 `.gitignore` 文件中的忽略模式(ignored patterns)。 - -`hooks` 目录包含客户端或服务端的钩子脚本(hook scripts)。 - -剩下的四个条目很重要:`HEAD` 文件、(尚待创建的)`index` 文件,和 `objects` 目录、`refs` 目录。 它们都是 Git 的核心组成部分。 - -`objects` 目录存储所有数据内容; +随着 Git 版本的不同,该目录下可能还会包含其他内容。不过对于一个全新的 `git init` 版本库,这将是你看到的默认结构: -`refs` 目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针; +- `description` 文件仅供 GitWeb 程序使用,我们无需关心。 +- `config` 文件包含项目特有的配置选项。 +- `info` 目录包含一个全局性排除(global exclude)文件, 用以放置那些不希望被记录在 `.gitignore` 文件中的忽略模式(ignored patterns)。 +- `hooks` 目录包含客户端或服务端的钩子脚本(hook scripts)。 -`HEAD` 文件指向目前被检出的分支; +剩下的四个条目很重要:`HEAD` 文件、(尚待创建的)`index` 文件,和 `objects` 目录、`refs` 目录。它们都是 Git 的核心组成部分。 -`index` 文件保存暂存区信息。 \ No newline at end of file +- `objects` 目录存储所有数据内容; +- `refs` 目录存储指向数据(分支、远程仓库和标签等)的提交对象的指针; +- `HEAD` 文件指向目前被检出的分支; +- `index` 文件保存暂存区信息。 \ No newline at end of file diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/2. Git \345\257\271\350\261\241.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/2. Git \345\257\271\350\261\241.md" index 5a4c6e43c5cf455cfe01f76f675e3e80738db350..26ae45d10f7b7ce86232bab115cb4d470de0873e 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/2. Git \345\257\271\350\261\241.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/2. Git \345\257\271\350\261\241.md" @@ -3,50 +3,56 @@ title: Git 对象 permalink: /git-tutorial/blob-object --- -Git包含四种基本对象类型: +Git 包含四种基本对象类型:blob object (数据对象)、tree object (树对象)、commit object (提交对象)和 tag object (标签对象)。 -## 1. blob object (数据对象)-文件系统的文件 +## blob object(数据对象) -git 中的 blob object 就是文件系统中的文件,包含 键:一个 hash 值和校验值的组合,值:文件内容。 +git 中的数据对象(blob object)就是**文件系统中的文件**,包含键:一个 hash 值和校验值的组合,值:文件内容。 -可以当成我们电脑资源管理器上各种各样的文件,比较特殊的是:blob object 只存内容,不包括文件名,路径,格式等信息。 +可以当成我们电脑资源管理器上各种各样的文件,比较特殊的是:blob object 只存内容,不包括文件名、路径、格式等信息。 -### **写入** +### 写入 -git hash-object 会接受你传给它的东西,而它只会返回可以存储在 Git 仓库中的唯一键。这个key的前6位即可找到指定的value +git hash-object 会接受你传给它的东西,而它只会返回可以存储在 Git 仓库中的唯一键。这个 key 的前 6 位即可找到指定的 value。 --w 选项会指示该命令不要只返回键,还要将该对象写入数据库中。 最后,--stdin 选项则指示该命令从标准输入读取内容;若不指定此选项,则须在命令尾部给出待存储文件的路径。 +`-w` 选项会指示该命令不要只返回键,还要将该对象写入数据库中。最后,`--stdin` 选项则指示该命令从标准输入读取内容;若不指定此选项,则须在命令尾部给出待存储文件的路径。 -### **读取** +### 读取 -可以通过cat-file命令从 Git 那里取回数据。 这个命令简直就是一把剖析 Git 对象的瑞士军刀。 +可以通过 cat-file 命令从 Git 那里取回数据。这个命令简直就是一把剖析 Git 对象的瑞士军刀。 -为cat-file指定-p选项可指示该命令自动判断内容的类型,并为我们显示大致的内容 +为 cat-file 指定 `-p` 选项可指示该命令自动判断内容的类型,并为我们显示大致的内容。 -git cat-file -p指返回存储的值 +`git cat-file -p` 指返回存储的值。 +```shell git show +``` -git cat-file -t指返回存储的对象类型 +`git cat-file -t` 指返回存储的对象类型。 -这部分感觉Git有点像Redis的味道,Git的核心部分就是一个键值对数据库(key-value data store) +这部分感觉 Git 有点像 Redis 的味道,Git 的核心部分就是一个键值对数据库(key-value data store)。 +```shell find .git/objects/ -type f +``` ![图片](./../../../.vuepress/public/images/qsECqUo3q28KIwRJ.png) ![图片](./../../../.vuepress/public/images/Zopmw5K2cxohB0Lq.png) -## 2. tree object (树对象)-文件系统的文件夹 -相当于文件系统中的文件夹。 但它包含了此目录下的数据对象,子目录(对应于子trees),文件名、路径等元数据。因此,对于有子目录的目录,Git相当于存储了嵌套的trees。 -树对象(tree object),它能解决文件名保存的问题,也允许我们将多个文件组织到一起。 Git 以一种类似于 UNIX 文件系统的方式存储内容,但作了些许简化。 所有内容均以树对象和数据对象的形式存储,其中树对象对应了 UNIX 中的目录项,数据对象则大致上对应了 inodes 或文件内容。 一个树对象包含了一条或多条树对象记录(tree entry),每条记录含有一个指向数据对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息。 例如,某项目当前对应的最新树对象可能是这样的: +## tree object(树对象) + +树对象(tree object)相当于文件系统中的文件夹。但它包含了此目录下的数据对象,子目录(对应于子 trees),文件名、路径等元数据。因此,对于有子目录的目录,Git 相当于存储了嵌套的 trees。 + +树对象(tree object),它能解决文件名保存的问题,也允许我们将多个文件组织到一起。Git 以一种类似于 UNIX 文件系统的方式存储内容,但作了些许简化。所有内容均以树对象和数据对象的形式存储,其中树对象对应了 UNIX 中的目录项,数据对象则大致上对应了 inodes 或文件内容。一个树对象包含了一条或多条树对象记录(tree entry),每条记录含有一个指向数据对象或者子树对象的 SHA-1 指针,以及相应的模式、类型、文件名信息。例如,某项目当前对应的最新树对象可能是这样的: ![图片](./../../../.vuepress/public/images/ZiF5Sph5hLguanmr.png) -提交新建的文件 +提交新建的文件: ```shell $ git add . @@ -58,41 +64,52 @@ $ git commit -m 'first commit'  create mode 100644 select/select.sql  create mode 100644 update.sql ``` -**使用 git cat-file -p 读取文件内容**,master^{tree}语法表示master分支上最新的提交所指向的树对象。 + +**使用 `git cat-file -p` 读取文件内容**,`master^{tree}` 语法表示 master 分支上最新的提交所指向的树对象。 ```shell $ git cat-file -p master^{tree} 100644 blob 7be9c19f6ca8802e1d8a1e017b0eb6a56db47320    delete.sql 100644 blob 2a313e0a83e07249fb263783edcde65af44f6331    insert.sql 040000 tree 715e56aa2f24831240cf204ecdb39fef9f61e0ea    select -100644 blob 37034df32709dfcc893f4828be7d023931400086    update.sql  +100644 blob 37034df32709dfcc893f4828be7d023931400086    update.sql ``` -请注意,select子目录(所对应的那条树对象记录)并不是一个数据对象,而是一个指针,其指向的是另一个树对象: + +请注意,select 子目录(所对应的那条树对象记录)并不是一个数据对象,而是一个指针,其指向的是另一个树对象: ![图片](./../../../.vuepress/public/images/g45g7c0sjvHInBV8.png) -### **新建 tree 对象** +### 新建 tree 对象 ```shell $ git write-tree d61a5c0a3dbe06d2b5d9e25f70e830fe9f98bbf2 ``` + 验证新建对象的类型 + ```shell $ git cat-file -t d61a5c0a3dbe06d2b5d9e25f70e830fe9f98bbf2 tree ``` -## 3. commit object (提交对象)-带有时间,作者等信息的文件夹 -提交对象可以理解为对树对象的一层封装,里面包含了提交一个更新的所有元数据,如指向的 tree,父 commit,作者、提交者、提交日期、提交日志等。 -### **指定 tree 对象为 commit 对象** + +## commit object(提交对象) + +提交对象(commit object)可以理解为对树对象的一层封装,里面包含了提交一个更新的所有元数据,如指向的 tree,父 commit,作者、提交者、提交日期、提交日志等。即带有时间、作者等信息的文件夹。 + +### 指定 tree 对象为 commit 对象 ```shell $ echo 'first commit' | git commit-tree 715e56 6237a66bba1736b5430d793e009357d750eea00c ``` -### **查看 commit 对象内容**,包括提交人提交时间,提交注释等 + +### 查看 commit 对象内容 + +查看 commit 对象内容,包括提交人提交时间、提交注释等: + ```shell $ git show 6237a6 commit 6237a66bba1736b5430d793e009357d750eea00c @@ -108,7 +125,8 @@ index 0000000..229377a +select * from table where 1=1 \ No newline at end of file ``` -### **查看提交历史** + +### 查看提交历史 ```shell $ git log @@ -121,36 +139,43 @@ Date:   Tue Aug 25 21:57:08 2020 +0800 ![图片](./../../../.vuepress/public/images/6VvpTFcnSSvZnxmA.png) - -## 4. tag object (标签对象)- 标签 +## tag object(标签对象) 可以给以上的任意对象打标签,但实际使用中,一般只会给提交打标签。 -### **列出现有 tag** +**列出现有 tag:** ```shell git tag ``` -### **查看指定 tag 的信息** + +**查看指定 tag 的信息:** + ```shell git show v1.2.3 ``` -### **查看包含指定提交的 tag** + +**查看包含指定提交的 tag:** + ```shell git tag --contains ``` -### **简单新建** + +**简单新建:** ```shell git tag v1.2.3 ``` -### **给指定 commit 添加带注释的 tag** + +**给指定 commit 添加带注释的 tag:** + ```shell git tag -a v1.2.3 -m "your message" 9fceb02 ``` -### **示例:** -查看提交记录 +### 示例 + +查看提交记录: ```shell $ git log @@ -163,17 +188,23 @@ Author: will Date:   Tue Aug 25 21:57:08 2020 +0800     first commit ``` -为提交添加Tag + +为提交添加 Tag: + ```shell $ git tag -a v1.2 -m "version 1.2" 9bfba6 ``` -查看Tag列表 + +查看 Tag 列表: + ```shell $ git tag v1 v1.2 ``` -查看Tag内容 + +查看 Tag 内容: + ```shell $ git show v1.2 tag v1.2 @@ -200,6 +231,8 @@ index 0000000..229377a @@ -0,0 +1 @@ +update table set id='22' where 1=1 ``` -**Tag存储位置** -![图片](./../../../.vuepress/public/images/muXdmBdgRZlIpPtt.png) \ No newline at end of file +Tag 存储位置: + +![图片](./../../../.vuepress/public/images/muXdmBdgRZlIpPtt.png) + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/3. Git \345\274\225\347\224\250.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/3. Git \345\274\225\347\224\250.md" index dabf08ccf46577bc3a3a9415bc4c72a541ff8a23..d3b8d9da3230c7c16f869344a4e0f230d3c7fbed 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/3. Git \345\274\225\347\224\250.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/3. Git \345\274\225\347\224\250.md" @@ -2,39 +2,46 @@ title: Git 引用 permalink: /git-tutorial/git-references --- + Git 引用,引用(references,缩写 refs) ![图片](./../../../.vuepress/public/images/8w7vKp54xjnNfwnp.png) -引用的目的是创建一个指针替代原始的 key(SHA-1值) +引用的目的是创建一个指针替代原始的 key(SHA-1值)。 ## 标签引用 -比如上篇提到的查询对象内容的命令 +比如上篇提到的查询对象内容的命令: ```shell git show ``` -如果我们给这个commit对象添加了Tag + +如果我们给这个 commit 对象添加了 Tag: + ```shell $ git tag -a v1.2 -m "version 1.2" 9bfba6 ``` -即可使用 `git show ` 的命令查看commit内容 + +即可使用 `git show ` 的命令查看 commit 内容: + ```shell $ git show v1.2 ``` + 这种方式叫做标签引用。 -还有别的引用方式,Head 引用和 Remote 引用 + +此外,还有其他引用方式,Head 引用和 Remote 引用。 ## HEAD 引用 -当你执行 `git branch ` 时,Git 如何知道最新提交的 SHA-1 值呢? 答案是 HEAD 文件。 +当你执行 `git branch ` 时,Git 如何知道最新提交的 SHA-1 值呢?答案是 HEAD 文件。 ![图片](./../../../.vuepress/public/images/vBunAKbOGd80gbfV.png) ![图片](./../../../.vuepress/public/images/rZTmEnRRjWEtlaIX.png) -HEAD 文件是可以手动编辑的,但我们有个更安全的命令来完成此事:git symbolic-ref。 也可以借助此命令来查看 HEAD 引用对应的值: +HEAD 文件是可以手动编辑的,但我们有个更安全的命令来完成此事:`git symbolic-ref`。也可以借助此命令来查看 HEAD 引用对应的值: ![图片](./../../../.vuepress/public/images/9aOgmzUIzoAizbny.png) @@ -44,10 +51,12 @@ remote reference ![图片](./../../../.vuepress/public/images/DhbbZTPI5wAGUasn.png) -如果项目有添加远程版本库 +如果项目有添加远程版本库: ```shell - $ cat .git/refs/remotes/origin/master +$ cat .git/refs/remotes/origin/master 24de949bb7c23ff052d5b39d01d809e86dd43fd2 ``` -远程引用和分支(位于 refs/heads 目录下的引用)之间最主要的区别在于,远程引用是只读的。 虽然可以 git checkout 到某个远程引用,但是 Git 并不会将 HEAD 引用指向该远程引用。因此,不能通过 commit 命令来更新远程引用。 Git 将这些远程引用作为记录远程服务器上各分支最后已知位置状态的书签来管理。 \ No newline at end of file + +远程引用和分支(位于 refs/heads 目录下的引用)之间最主要的区别在于,远程引用是只读的。虽然可以 `git checkout` 到某个远程引用,但是 Git 并不会将 HEAD 引用指向该远程引用。因此,不能通过 `commit` 命令来更新远程引用。Git 将这些远程引用作为记录远程服务器上各分支最后已知位置状态的书签来管理。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/4. \345\214\205\346\226\207\344\273\266.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/4. \345\214\205\346\226\207\344\273\266.md" index 61b1c10ec1597f95efb3806cf5aaab5574fbfb90..0c852a2663160d1b1859196051417132df7bdb49 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/4. \345\214\205\346\226\207\344\273\266.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/4. \345\214\205\346\226\207\344\273\266.md" @@ -3,20 +3,20 @@ title: 包文件 permalink: /git-tutorial/git-files --- -新建了一个 出师表txt +新建了一个出师表.txt ![图片](./../../../.vuepress/public/images/0hvzNnN8rcJ9Iyx8.png) -新增提交后 - -查看文件 +新增提交后,查看文件: ```shell $ git cat-file -p master^{tree} 100644 blob cd32d11c26f2909e3204e327bbd2685a87baf660 CSB.txt ``` -修改这个文件,在最后加了几行文字 -新增提交后 查看文件 + +修改这个文件,在最后加了几行文字。 + +新增提交后,查看文件: ```shell $ git add . @@ -26,8 +26,10 @@ $ git commit -m 'v2' $ git cat-file -p master^{tree} 100644 blob f3858d435146e27364574fa97936b45bec65663e CSB.txt ``` -发现两次文件是不一样的 -查看文件大小 + +发现两次文件是不一样的。 + +查看文件大小: ```shell $ git cat-file -s cd32d1 @@ -35,12 +37,14 @@ $ git cat-file -s cd32d1 $ git cat-file -s f3858d 1561 ``` + 这就是说,无论对这个文件做了多小的改动,Git 都会新建一个对象来保存新的内容。 -这也造成了 Git 存储了前面大量内容是重复的,这种最初的存储对象格式称为“松散(loose)”对象格式 -但是,Git 会时常将多个这些对象打包成一个称为“包文件(packfile)”的二进制文件,以节省空间和提高效率。 当版本库中有太多的松散对象,或者我们手动执行`git gc`命令,再或者我们向远程服务器执行推送时,Git 都会执行打包过程。 +这也造成了 Git 存储了前面大量内容是重复的,这种最初的存储对象格式称为“松散(loose)”对象格式。 -首先,我们查看当前对象列表,有一堆数据和提交对象 +但是,Git 会时常将多个这些对象打包成一个称为“包文件(packfile)”的二进制文件,以节省空间和提高效率。当版本库中有太多的松散对象,或者我们手动执行 `git gc` 命令,再或者我们向远程服务器执行推送时,Git 都会执行打包过程。 + +首先,我们查看当前对象列表,有一堆数据和提交对象。 ```shell $ find .git/objects -type f @@ -52,7 +56,9 @@ $ find .git/objects -type f .git/objects/f3/858d435146e27364574fa97936b45bec65663e .git/objects/f5/abd87faf2abc34e7d1ac18e7e020f7d4e1c547 ``` -然后我们执行`git gc`命令 + +然后我们执行 `git gc` 命令: + ```shell $ git gc Enumerating objects: 6, done. @@ -62,7 +68,9 @@ Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), done. Total 6 (delta 1), reused 0 (delta 0) ``` -再次查看对象列表,发现内容已打包 + +再次查看对象列表,发现内容已打包: + ```shell $ find .git/objects -type f .git/objects/54/68f3283bfc7fd3ae3cf17e89210b744d106e48 @@ -70,7 +78,9 @@ $ find .git/objects -type f .git/objects/pack/pack-5035b9fb775a699fecee6ac3c3df69734a095758.idx .git/objects/pack/pack-5035b9fb775a699fecee6ac3c3df69734a095758.pack ``` -使用`git verify-pack`命令可以查看打包的内容 + +使用 `git verify-pack` 命令可以查看打包的内容: + ```shell $ git verify-pack -v .git/objects/pack/pack-5035b9fb775a699fecee6ac3c3df69734a095758.idx @@ -85,4 +95,6 @@ non delta: 5 objects chain length = 1: 1 object .git/objects/pack/pack-5035b9fb775a699fecee6ac3c3df69734a095758.pack: ok ``` -可以看到对象`f3858d`为1561字节,为修改后的最新内容,另外一个对象`cd32d1`引用了`f3858d`,也就是保存了所有文件内容,且只占用7字节。 \ No newline at end of file + +可以看到对象 `f3858d` 为 1561 字节,为修改后的最新内容,另外一个对象 `cd32d1` 引用了 `f3858d`,也就是保存了所有文件内容,且只占用 7 字节。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/5. \345\274\225\347\224\250\350\247\204\350\214\203.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/5. \345\274\225\347\224\250\350\247\204\350\214\203.md" index 4d4ed918f5352a15a15dea0d2475f14811bcdf06..f1d9c484468b9d7783c62099b197b008adc25c0d 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/5. \345\274\225\347\224\250\350\247\204\350\214\203.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/5. \345\274\225\347\224\250\350\247\204\350\214\203.md" @@ -2,39 +2,46 @@ title: 引用规范 permalink: /git-tutorial/reference-specification --- + ## 引用规范设置 -添加远程仓库的命令会在`.git/config`文件中添加一个小节, 并在其中指定远程版本库的名称(origin)、URL 和一个用于获取操作的 引用规范(refspec) +添加远程仓库的命令会在 `.git/config` 文件中添加一个小节, 并在其中指定远程版本库的名称(origin)、URL 和一个用于获取操作的 引用规范(refspec)。 ```shell git remote add origin https://gitee.com/willcoder/fake-project.git ``` + ![图片](./../../../.vuepress/public/images/uHKgz843SOvsYMNZ.png) -引用规范的格式由一个可选的 + 号和紧随其后的`:`组成, 其中``代表远程版本库中的引用;``是本地跟踪的远程引用的位置。 + 号告诉 Git 即使在不能快进的情况下也要(强制)更新引用。 +引用规范的格式由一个可选的 + 号和紧随其后的 `:` 组成,其中 `` 代表远程版本库中的引用;`` 是本地跟踪的远程引用的位置。+ 号告诉 Git 即使在不能快进的情况下也要(强制)更新引用。 -默认情况下,引用规范由`git remote add origin`命令自动生成, Git 获取服务器中`refs/heads/`下面的所有引用,并将它写入到本地的`refs/remotes/origin/`中。 所以,如果服务器上有一个`master`分支,你可以在本地通过下面任意一种方式来访问该分支上的提交记录: +默认情况下,引用规范由 `git remote add origin` 命令自动生成,Git 获取服务器中 `refs/heads/` 下面的所有引用,并将它写入到本地的 `refs/remotes/origin/` 中。所以,如果服务器上有一个 `master` 分支,你可以在本地通过下面任意一种方式来访问该分支上的提交记录: ```shell $ git log origin/master $ git log remotes/origin/master $ git log refs/remotes/origin/master ``` -上面的三个命令作用相同,因为 Git 会把它们都扩展成`refs/remotes/origin/master`。 -如果想让 Git 每次只拉取远程的`master`分支,而不是所有分支, 可以把(引用规范的)获取那一行修改为只引用该分支: + +上面的三个命令作用相同,因为 Git 会把它们都扩展成 `refs/remotes/origin/master`。 + +如果想让 Git 每次只拉取远程的 `master` 分支,而不是所有分支,可以把(引用规范的)获取那一行修改为只引用该分支: ```shell fetch = +refs/heads/master:refs/remotes/origin/master ``` + 这种方式会默认修改引用规范,如果只希望被执行一次的操作,我们可以在命令行中指定引用规范。 -若要将远程的`master`分支拉到本地的`origin/mymaster`分支,可以运行: + +若要将远程的 `master` 分支拉到本地的 `origin/mymaster` 分支,可以运行: ```shell git fetch origin master:refs/remotes/origin/mymaster ``` + ![图片](./../../../.vuepress/public/images/B9haCkozj7Ux0ID0.png) -也可以指定多个引用规范。 在命令行中,你可以按照如下的方式拉取多个分支: +也可以指定多个引用规范。在命令行中,你可以按照如下的方式拉取多个分支: ```shell $ git fetch origin master:refs/remotes/origin/mymaster \ @@ -43,8 +50,10 @@ From https://gitee.com/willcoder/fake-project.git ! [rejected] master -> origin/mymaster (non fast forward) * [new branch] topic -> origin/topic ``` -在这个例子中,对`master`分支的拉取操作被拒绝,因为它不是一个可以快进的引用。 我们可以通过在引用规范之前指定`+`号来覆盖该规则。 -你也可以在配置文件中指定多个用于获取操作的引用规范。 如果想在每次从 origin 远程仓库获取时都包括`master`和`featureA`分支,添加如下两行: + +在这个例子中,对 `master` 分支的拉取操作被拒绝,因为它不是一个可以快进的引用。我们可以通过在引用规范之前指定 `+` 号来覆盖该规则。 + +你也可以在配置文件中指定多个用于获取操作的引用规范。如果想在每次从 origin 远程仓库获取时都包括 `master` 和 `featureA` 分支,添加如下两行: ```shell [remote "origin"] @@ -52,6 +61,7 @@ url = https://gitee.com/willcoder/fake-project.git fetch = +refs/heads/master:refs/remotes/origin/master fetch = +refs/heads/featureA:refs/remotes/origin/featureA ``` + ![图片](./../../../.vuepress/public/images/eM5r3c8QGBFqD43D.png) 我们不能在模式中使用部分通配符,所以像下面这样的引用规范是不合法的: @@ -59,8 +69,10 @@ fetch = +refs/heads/featureA:refs/remotes/origin/featureA ```shell fetch = +refs/heads/qa*:refs/remotes/origin/qa* ``` + 但我们可以使用命名空间(或目录)来达到类似目的。 -假设你有一个 QA 团队,他们推送了一系列分支,同时你只想要获取`master`和 QA 团队的所有分支而不关心其他任何分支,那么可以使用如下配置: + +假设你有一个 QA 团队,他们推送了一系列分支,同时你只想要获取 `master` 和 QA 团队的所有分支而不关心其他任何分支,那么可以使用如下配置: ```shell [remote "origin"] @@ -68,26 +80,31 @@ url = https://gitee.com/willcoder/fake-project.git fetch = +refs/heads/master:refs/remotes/origin/master fetch = +refs/heads/qa/*:refs/remotes/origin/qa/* ``` + 如果项目的工作流很复杂,有 QA 团队推送分支、开发人员推送分支、集成团队推送并且在远程分支上展开协作,你就可以像这样(在本地)为这些分支创建各自的命名空间,非常方便。 + ## 引用规范推送 -像上面这样从远程版本库获取已在命名空间中的引用当然很棒,但 QA 团队最初应该如何将他们的分支放入远程的`qa/`命名空间呢? 我们可以通过引用规范推送来完成这个任务。 +像上面这样从远程版本库获取已在命名空间中的引用当然很棒,但 QA 团队最初应该如何将他们的分支放入远程的 `qa/` 命名空间呢?我们可以通过引用规范推送来完成这个任务。 -如果 QA 团队想把他们的`master`分支推送到远程服务器的`qa/master`分支上,可以运行: +如果 QA 团队想把他们的 `master` 分支推送到远程服务器的 `qa/master` 分支上,可以运行: ```shell $ git push origin master:refs/heads/qa/master ``` -如果他们希望 Git 每次运行`git push origin`时都像上面这样推送,可以在他们的配置文件中添加一条`push`值: + +如果他们希望 Git 每次运行 `git push origin` 时都像上面这样推送,可以在他们的配置文件中添加一条 `push` 值: + ```shell [remote "origin"] url = https://gitee.com/willcoder/fake-project.git fetch = +refs/heads/*:refs/remotes/origin/* push = refs/heads/master:refs/heads/qa/master ``` + ![图片](./../../../.vuepress/public/images/zNpI6xmnmWS2cGS0.png) -正如刚才所指出的,这会让`git push origin`默认把本地`master`分支推送到远程`qa/master`分支 +正如刚才所指出的,这会让 `git push origin` 默认把本地 `master` 分支推送到远程 `qa/master` 分支。 ## 删除引用 @@ -96,9 +113,12 @@ push = refs/heads/master:refs/heads/qa/master ```shell $ git push origin :topic ``` -因为引用规范(的格式)是`:`,所以上述命令把``留空,意味着把远程版本库的 topic 分支定义为空值,也就是删除它。 + +因为引用规范(的格式)是 `:`,所以上述命令把 `` 留空,意味着把远程版本库的 topic 分支定义为空值,也就是删除它。 + 或者你可以使用更新的语法(自 Git v1.7.0 以后可用): ```shell $ git push origin --delete topic -``` \ No newline at end of file +``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/6. \344\274\240\350\276\223\345\215\217\350\256\256.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/6. \344\274\240\350\276\223\345\215\217\350\256\256.md" index 07860814a69ceda52a90fcc9c35ee44c8ef136e6..5c61142ad3698f1cfcf192d4bc0c0c6114ea0555 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/6. \344\274\240\350\276\223\345\215\217\350\256\256.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/6. \344\274\240\350\276\223\345\215\217\350\256\256.md" @@ -2,7 +2,8 @@ title: 传输协议 permalink: /git-tutorial/transport-protocol --- -Git 可以通过两种主要的方式在版本库之间传输数据:“哑(dumb)”协议和“智能(smart)”协议。 + +Git 可以通过两种主要的方式在版本库之间传输数据:“哑(dumb)” 协议和 “智能(smart)” 协议。 ## 哑协议 @@ -10,7 +11,7 @@ Git 可以通过两种主要的方式在版本库之间传输数据:“哑(d 在传输过程中,服务端不需要有针对 Git 特有的代码;抓取过程是一系列 HTTP 的 GET 请求,这种情况下,客户端可以推断出服务端 Git 仓库的布局。所以使用哑协议的版本库很难保证安全性和私有化,所以现在基本很少使用到了。 -"哑协议"的只读限制是因为其服务端没有一个Git的守护进程在持续的关注"客户端"的所需并与之关注,所以只能“客户端”去发起请求获取远程的变更。 +“哑协议”的只读限制是因为其服务端没有一个 Git 的守护进程在持续的关注“客户端”的所需并与之关注,所以只能“客户端”去发起请求获取远程的变更。 @@ -22,18 +23,17 @@ Git 可以通过两种主要的方式在版本库之间传输数据:“哑(d ### 上传数据 -为了上传数据至远端,Git 使用`send-pack`和`receive-pack`进程。 运行在客户端上的`send-pack`进程连接到远端运行的`receive-pack`进程。 - -比如在我们执行`git push origin master`的时候: +为了上传数据至远端,Git 使用 `send-pack` 和 `receive-pack` 进程。运行在客户端上的 `send-pack` 进程连接到远端运行的 `receive-pack` 进程。 -1.Git会执行`send-pack`进程连接服务器,`git-receive-pack`命令会立即为它所拥有的每一个引用发送一行响应。 +比如在我们执行 `git push origin master` 的时候: -2.你的`send-pack`进程会判断哪些提交记录是它所拥有但服务端没有的。`send-pack`会告知`receive-pack`这次推送将会更新的各个引用。服务端在收到请求后相应地作出成功或失败的 HTTP 响应。 +1. Git 会执行 `send-pack` 进程连接服务器,`git-receive-pack` 命令会立即为它所拥有的每一个引用发送一行响应。 +2. 你的 `send-pack` 进程会判断哪些提交记录是它所拥有但服务端没有的。`send-pack` 会告知 `receive-pack` 这次推送将会更新的各个引用。服务端在收到请求后相应地作出成功或失败的 HTTP 响应。 ### 下载数据 -当你在下载数据时,`fetch-pack`和`upload-pack`进程就起作用了。 客户端启动`fetch-pack`进程,连接至远端的`upload-pack`进程,以协商后续传输的数据。 +当你在下载数据时,`fetch-pack` 和 `upload-pack` 进程就起作用了。客户端启动 `fetch-pack` 进程,连接至远端的 `upload-pack` 进程,以协商后续传输的数据。 -1.`fetch-pack`连接远程服务器,然后`upload-pack`会返回类似`receive-pack`返回的内容。 +1. `fetch-pack` 连接远程服务器,然后 `upload-pack` 会返回类似 `receive-pack` 返回的内容。 +2. `fetch-pack` 进程查看它自己所拥有的对象,并响应 “want” 和它需要的对象的 SHA-1 值。它还会发送 “have” 和所有它已拥有的对象的 SHA-1 值。在列表的最后,它还会发送 “done” 以通知 `upload-pack` 进程可以开始发送它所需对象的包文件。 -2.`fetch-pack`进程查看它自己所拥有的对象,并响应 “want” 和它需要的对象的 SHA-1 值。 它还会发送“have”和所有它已拥有的对象的 SHA-1 值。 在列表的最后,它还会发送“done”以通知`upload-pack`进程可以开始发送它所需对象的包文件。 diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/7. \347\273\264\346\212\244\344\270\216\346\225\260\346\215\256\346\201\242\345\244\215.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/7. \347\273\264\346\212\244\344\270\216\346\225\260\346\215\256\346\201\242\345\244\215.md" index bb7158584ab8c0756dc433a6e23efd22b3954e91..f5d54974957a6721ea9d1dd5632e86cac4baff68 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/7. \347\273\264\346\212\244\344\270\216\346\225\260\346\215\256\346\201\242\345\244\215.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/7. \347\273\264\346\212\244\344\270\216\346\225\260\346\215\256\346\201\242\345\244\215.md" @@ -2,13 +2,14 @@ title: 维护与数据恢复 permalink: /git-tutorial/recover --- + ## 维护 -Git 会不定时地自动运行一个叫做 “auto gc” 的命令。 大多数时候,这个命令并不会产生效果。 然而,如果有太多松散对象(不在包文件中的对象)或者太多包文件,Git 会运行一个完整的`git gc`命令,我们可以通过修改`gc.auto`与`gc.autopacklimit`的设置来改动这些限制数值。 +Git 会不定时地自动运行一个叫做 “auto gc” 的命令。 大多数时候,这个命令并不会产生效果。 然而,如果有太多松散对象(不在包文件中的对象)或者太多包文件,Git 会运行一个完整的 `git gc` 命令,我们可以通过修改 `gc.auto` 与 `gc.autopacklimit` 的设置来改动这些限制数值。 “gc” 代表垃圾回收,这个命令会做以下事情:收集所有松散对象并将它们放置到包文件中, 将多个包文件合并为一个大的包文件,移除与任何提交都不相关的陈旧对象。 -首先,我们查看当前对象列表,有一堆松散数据对象 +首先,我们查看当前对象列表,有一堆松散数据对象: ```shell $ find .git/objects -type f @@ -20,7 +21,9 @@ $ find .git/objects -type f .git/objects/f3/858d435146e27364574fa97936b45bec65663e .git/objects/f5/abd87faf2abc34e7d1ac18e7e020f7d4e1c547 ``` -然后我们执行`git gc`命令 + +然后我们执行 `git gc` 命令: + ```shell $ git gc Enumerating objects: 6, done. @@ -30,7 +33,9 @@ Compressing objects: 100% (4/4), done. Writing objects: 100% (6/6), done. Total 6 (delta 1), reused 0 (delta 0) ``` -再次查看对象列表,发现内容已打包 + +再次查看对象列表,发现内容已打包: + ```shell $ find .git/objects -type f .git/objects/54/68f3283bfc7fd3ae3cf17e89210b744d106e48 @@ -39,7 +44,7 @@ $ find .git/objects -type f .git/objects/pack/pack-5035b9fb775a699fecee6ac3c3df69734a095758.pack ``` -`gc`将会做的另一件事是打包你的引用到一个单独的文件。 假设你的仓库包含以下分支与标签: +`gc` 将会做的另一件事是打包你的引用到一个单独的文件。假设你的仓库包含以下分支与标签: ```shell $ find .git/refs -type f @@ -48,7 +53,9 @@ $ find .git/refs -type f .git/refs/tags/v1.0 .git/refs/tags/v1.1 ``` -如果你执行了`git gc`命令,`refs`目录中将不会再有这些文件。 为了保证效率 Git 会将它们移动到名为`.git/packed-refs`的文件中,就像这样: + +如果你执行了 `git gc` 命令,`refs` 目录中将不会再有这些文件。为了保证效率 Git 会将它们移动到名为 `.git/packed-refs` 的文件中,就像这样: + ```shell $ cat .git/packed-refs # pack-refs with: peeled fully-peeled @@ -58,12 +65,14 @@ cac0cab538b970a37ea1e769cbbde608743bc96d refs/tags/v1.0 9585191f37f7b0fb9444f35a9bf50de191beadc2 refs/tags/v1.1 ^1a410efbd13591db07496601ebc7a059dd55cfe9 ``` -如果你更新了引用,Git 并不会修改这个文件,而是向`refs/heads`创建一个新的文件。 为了获得指定引用的正确 SHA-1 值,Git 会首先在`refs`目录中查找指定的引用,然后再到`packed-refs`文件中查找。 所以,如果你在`refs`目录中找不到一个引用,那么它或许在`packed-refs`文件中。 + +如果你更新了引用,Git 并不会修改这个文件,而是向 `refs/heads` 创建一个新的文件。为了获得指定引用的正确 SHA-1 值,Git 会首先在 `refs` 目录中查找指定的引用,然后再到 `packed-refs` 文件中查找。所以,如果你在 `refs` 目录中找不到一个引用,那么它或许在 `packed-refs` 文件中。 + ## 数据恢复 -在使用 Git 的过程中,如果强制删除了正在工作的分支,或者硬重置了一个分支,这时我们会丢失一些提交。 如果我们还需要这些提交,那我们就需要用到数据恢复。 +在使用 Git 的过程中,如果强制删除了正在工作的分支,或者硬重置了一个分支,这时我们会丢失一些提交。如果我们还需要这些提交,那我们就需要用到数据恢复。 -下面的例子将硬重置你的测试仓库中的`master`分支到一个旧的提交,以此来恢复丢失的提交。 首先,让我们看看你的仓库现在在什么地方: +下面的例子将硬重置你的测试仓库中的 `master` 分支到一个旧的提交,以此来恢复丢失的提交。首先,让我们看看你的仓库现在在什么地方: ```shell $ git log --pretty=oneline @@ -74,7 +83,9 @@ ea561d5fded583caca9a81d8cdefede2f77240b2 (origin/featureA) insert d3c8035e27d3efdb4333867757f34c1ba966a852 git merge ca671b5cd1739aa6aa887e5ef9d0a04bcbd65a05 init ``` -现在,我们将`master`分支硬重置到第三次提交: + +现在,我们将 `master` 分支硬重置到第三次提交: + ```shell $ git reset --hard 24de949bb7c23ff052d5b39d01d809e86dd43fd2 HEAD is now at 24de949 git apply @@ -84,8 +95,10 @@ ea561d5fded583caca9a81d8cdefede2f77240b2 (origin/featureA) insert d3c8035e27d3efdb4333867757f34c1ba966a852 git merge ca671b5cd1739aa6aa887e5ef9d0a04bcbd65a05 init ``` -现在顶部的两个提交已经丢失了——没有分支指向这些提交。 你需要找出最后一次提交的 SHA-1 然后增加一个指向它的分支。 -最方便,也是最常用的方法,是使用一个名叫`git reflog`的工具。 当你正在工作时,Git 会默默地记录每一次你改变 HEAD 时它的值。 每一次你提交或改变分支,引用日志都会被更新。 引用日志(reflog)也可以通过`git update-ref`命令更新。 你可以在任何时候通过执行`git reflog`命令来了解你曾经做过什么: + +现在顶部的两个提交已经丢失了 —— 没有分支指向这些提交。你需要找出最后一次提交的 SHA-1 然后增加一个指向它的分支。 + +最方便,也是最常用的方法,是使用一个名叫 `git reflog` 的工具。当你正在工作时,Git 会默默地记录每一次你改变 HEAD 时它的值。每一次你提交或改变分支,引用日志都会被更新。引用日志(reflog)也可以通过 `git update-ref` 命令更新。你可以在任何时候通过执行 `git reflog` 命令来了解你曾经做过什么: ```shell $ git reflog @@ -94,7 +107,9 @@ e201e95 HEAD@{1}: commit: update submit.sh 421f3b6 HEAD@{2}: commit: delete patch,add new file 24de949 HEAD@{3}: clone: from https://gitee.com/willcoder/fake-project.git ``` -这里可以看到我们已经检出的两次提交,然而并没有足够多的信息。 为了使显示的信息更加有用,我们可以执行`git log -g`,这个命令会以标准日志的格式输出引用日志。 + +这里可以看到我们已经检出的两次提交,然而并没有足够多的信息。为了使显示的信息更加有用,我们可以执行 `git log -g`,这个命令会以标准日志的格式输出引用日志。 + ```shell $ git log -g commit 24de949bb7c23ff052d5b39d01d809e86dd43fd2 @@ -122,7 +137,9 @@ Author: will Date:   Mon Aug 24 23:09:28 2020 +0800     git apply ``` -看起来下面的那个就是你丢失的提交,你可以通过创建一个新的分支指向这个提交来恢复它。 例如,你可以创建一个名为 recover-branch 的分支指向这个提交(e201e9): + +看起来下面的那个就是你丢失的提交,你可以通过创建一个新的分支指向这个提交来恢复它。例如,你可以创建一个名为 recover-branch 的分支指向这个提交(e201e9): + ```shell $ git branch recover-branch e201e9 $ git log --pretty=oneline recover-branch @@ -133,29 +150,35 @@ ea561d5fded583caca9a81d8cdefede2f77240b2 (origin/featureA) insert d3c8035e27d3efdb4333867757f34c1ba966a852 git merge ca671b5cd1739aa6aa887e5ef9d0a04bcbd65a05 init ``` -不错,现在有一个名为`recover-branch`的分支是你的`master`分支曾经指向的地方, 再一次使得前两次提交可到达了。接下来,假设你丢失的提交因为某些原因不在引用日志中, 那么我们可以通过移除`recover-branch`分支并删除引用日志来模拟这种情况。 现在前两次提交又不被任何分支指向了: + +不错,现在有一个名为 `recover-branch` 的分支是你的 `master` 分支曾经指向的地方,再一次使得前两次提交可到达了。接下来,假设你丢失的提交因为某些原因不在引用日志中,那么我们可以通过移除 `recover-branch` 分支并删除引用日志来模拟这种情况。现在前两次提交又不被任何分支指向了: + ```shell -删除分支 +# 删除分支 $ git branch -D recover-branch Deleted branch recover-branch (was e201e95). -删除日志 + +# 删除日志 $ rm -Rf .git/logs/ -使用git fsck --full获取丢失的提交SHA-1 + +# 使用 git fsck --full 获取丢失的提交 SHA-1 $ git fsck --full Checking object directories: 100% (256/256), done. Checking objects: 100% (25/25), done. dangling commit e201e95d4814f8c5c7522755ae6151b298b9ea4a ``` + 在这个例子中,你可以在 “dangling commit” 后看到你丢失的提交。 + ## 移除对象 -`git clone`会下载整个项目的历史,包括每一个文件的每一个版本。 如果所有的东西都是源代码那么这很好,因为 Git 被高度优化来有效地存储这种数据。 如果某个人在之前向项目添加了一个大小特别大的文件,即使你将这个文件从项目中移除了,每次克隆还是都要强制的下载这个大文件。 之所以会产生这个问题,是因为这个文件在历史中是存在的,它会永远在那里。 +`git clone` 会下载整个项目的历史,包括每一个文件的每一个版本。如果所有的东西都是源代码那么这很好,因为 Git 被高度优化来有效地存储这种数据。如果某个人在之前向项目添加了一个大小特别大的文件,即使你将这个文件从项目中移除了,每次克隆还是都要强制的下载这个大文件。之所以会产生这个问题,是因为这个文件在历史中是存在的,它会永远在那里。 -当你迁移 Subversion 或 Perforce 仓库到 Git 的时候,这会是一个严重的问题。 因为这些版本控制系统并不下载所有的历史文件,所以这种文件所带来的问题比较少。 如果你从其他的版本控制系统迁移到 Git 时发现仓库比预期的大得多,那么你就需要找到并移除这些大文件。 +当你迁移 Subversion 或 Perforce 仓库到 Git 的时候,这会是一个严重的问题。因为这些版本控制系统并不下载所有的历史文件,所以这种文件所带来的问题比较少。如果你从其他的版本控制系统迁移到 Git 时发现仓库比预期的大得多,那么你就需要找到并移除这些大文件。 -**警告:这个操作对提交历史的修改是破坏性的。**它会从你必须修改或移除一个大文件引用最早的树对象开始重写每一次提交。 +**警告:这个操作对提交历史的修改是破坏性的。** 它会从你必须修改或移除一个大文件引用最早的树对象开始重写每一次提交。 -为了演示,我们将添加一个大文件到测试仓库中,并在下一次提交中删除它,现在我们需要找到它,并将它从仓库中永久删除。 首先,添加一个大文件到仓库中: +为了演示,我们将添加一个大文件到测试仓库中,并在下一次提交中删除它,现在我们需要找到它,并将它从仓库中永久删除。首先,添加一个大文件到仓库中: ```shell $ curl https://www.kernel.org/pub/software/scm/git/git-2.1.0.tar.gz > git.tgz @@ -165,7 +188,9 @@ $ git commit -m 'add git tarball' 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 git.tgz ``` -哎呀——其实这个项目并不需要这个巨大的压缩文件。 现在我们将它移除: + +哎呀 —— 其实这个项目并不需要这个巨大的压缩文件。现在我们将它移除: + ```shell $ git rm git.tgz rm 'git.tgz' @@ -174,7 +199,9 @@ $ git commit -m 'oops - removed large tarball' 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 git.tgz ``` -现在,我们执行`gc`来查看数据库占用了多少空间: + +现在,我们执行 `gc` 来查看数据库占用了多少空间: + ```shell $ git gc Counting objects: 17, done. @@ -183,7 +210,9 @@ Compressing objects: 100% (13/13), done. Writing objects: 100% (17/17), done. Total 17 (delta 1), reused 10 (delta 0) ``` -你也可以执行`count-objects`命令来快速的查看占用空间大小: + +你也可以执行 `count-objects` 命令来快速的查看占用空间大小: + ```shell $ git count-objects -v count: 7 @@ -195,8 +224,10 @@ prune-packable: 0 garbage: 0 size-garbage: 0 ``` -`size-pack`的数值指的是你的包文件以 KB 为单位计算的大小,所以你大约占用了 5MB 的空间。 在最后一次提交前,使用了不到 2KB ——显然,从之前的提交中移除文件并不能从历史中移除它。 每一次有人克隆这个仓库时,他们将必须克隆所有的 5MB 来获得这个微型项目,只因为你意外地添加了一个大文件。 现在来让我们彻底的移除这个文件。 -首先你必须找到它。 在本例中,你已经知道是哪个文件了。 但是假设你不知道;该如何找出哪个文件或哪些文件占用了如此多的空间? 如果你执行`git gc`命令,所有的对象将被放入一个包文件中,你可以通过运行`git verify-pack`命令, 然后对输出内容的第三列(即文件大小)进行排序,从而找出这个大文件。 你也可以将这个命令的执行结果通过管道传送给`tail`命令,因为你只需要找到列在最后的几个大对象。 + +`size-pack` 的数值指的是你的包文件以 KB 为单位计算的大小,所以你大约占用了 5MB 的空间。在最后一次提交前,使用了不到 2KB —— 显然,从之前的提交中移除文件并不能从历史中移除它。每一次有人克隆这个仓库时,他们将必须克隆所有的 5MB 来获得这个微型项目,只因为你意外地添加了一个大文件。现在来让我们彻底的移除这个文件。 + +首先你必须找到它。在本例中,你已经知道是哪个文件了。但是假设你不知道;该如何找出哪个文件或哪些文件占用了如此多的空间?如果你执行 `git gc` 命令,所有的对象将被放入一个包文件中,你可以通过运行 `git verify-pack` 命令,然后对输出内容的第三列(即文件大小)进行排序,从而找出这个大文件。你也可以将这个命令的执行结果通过管道传送给 `tail` 命令,因为你只需要找到列在最后的几个大对象。 ```shell $ git verify-pack -v .git/objects/pack/pack-29…69.idx \ @@ -206,18 +237,24 @@ dadf7258d699da2c8d89b09ef6670edb7d5f91b4 commit 229 159 12 033b4468fa6b2a9547a70d88d1bbe8bf3f9ed0d5 blob 22044 5792 4977696 82c99a3e86bb1267b236a4b6eff7868d97489af1 blob 4975916 4976258 1438 ``` -你可以看到这个大对象出现在返回结果的最底部:占用 5MB 空间。 为了找出具体是哪个文件,可以使用`rev-list`命令。 如果你传递`--objects`参数给`rev-list`命令,它就会列出所有提交的 SHA-1、数据对象的 SHA-1 和与它们相关联的文件路径。 可以使用以下命令来找出你的数据对象的名字: + +你可以看到这个大对象出现在返回结果的最底部:占用 5MB 空间。为了找出具体是哪个文件,可以使用 `rev-list` 命令。如果你传递 `--objects` 参数给 `rev-list` 命令,它就会列出所有提交的 SHA-1、数据对象的 SHA-1 和与它们相关联的文件路径。可以使用以下命令来找出你的数据对象的名字: + ```shell $ git rev-list --objects --all | grep 82c99a3 82c99a3e86bb1267b236a4b6eff7868d97489af1 git.tgz ``` -现在,你只需要从过去所有的树中移除这个文件。 使用以下命令可以轻松地查看哪些提交对这个文件产生改动: + +现在,你只需要从过去所有的树中移除这个文件。使用以下命令可以轻松地查看哪些提交对这个文件产生改动: + ```shell $ git log --oneline --branches -- git.tgz dadf725 oops - removed large tarball 7b30847 add git tarball ``` -现在,你必须重写`7b30847`提交之后的所有提交来从 Git 历史中完全移除这个文件。 为了执行这个操作,我们要使用`filter-branch`命令: + +现在,你必须重写 `7b30847` 提交之后的所有提交来从 Git 历史中完全移除这个文件。为了执行这个操作,我们要使用 `filter-branch` 命令: + ```shell $ git filter-branch --index-filter \ 'git rm --ignore-unmatch --cached git.tgz' -- 7b30847^.. @@ -225,10 +262,12 @@ Rewrite 7b30847d080183a1ab7d18fb202473b3096e9f34 (1/2)rm 'git.tgz' Rewrite dadf7258d699da2c8d89b09ef6670edb7d5f91b4 (2/2) Ref 'refs/heads/master' was rewritten ``` -`--index-filter`选项类似于`--tree-filter`选项, 不过这个选项并不会让命令将修改在硬盘上检出的文件,而只是修改在暂存区或索引中的文件。 -你必须使用`git rm --cached`命令来移除文件,而不是通过类似`rm file`的命令——因为你需要从索引中移除它,而不是磁盘中。 还有一个原因是速度—— Git 在运行过滤器时,并不会检出每个修订版本到磁盘中,所以这个过程会非常快。 如果愿意的话,你也可以通过`--tree-filter`选项来完成同样的任务。`git rm`命令的`--ignore-unmatch`选项告诉命令:如果尝试删除的模式不存在时,不提示错误。 最后,使用`filter-branch`选项来重写自`7b30847`提交以来的历史,也就是这个问题产生的地方。 否则,这个命令会从最旧的提交开始,这将会花费许多不必要的时间。 -你的历史中将不再包含对那个文件的引用。 不过,你的引用日志和你在`.git/refs/original`通过`filter-branch`选项添加的新引用中还存有对这个文件的引用,所以你必须移除它们然后重新打包数据库。 在重新打包前需要移除任何包含指向那些旧提交的指针的文件: +`--index-filter` 选项类似于 `--tree-filter` 选项,不过这个选项并不会让命令将修改在硬盘上检出的文件,而只是修改在暂存区或索引中的文件。 + +你必须使用 `git rm --cached` 命令来移除文件,而不是通过类似 `rm file` 的命令 —— 因为你需要从索引中移除它,而不是磁盘中。还有一个原因是速度 —— Git 在运行过滤器时,并不会检出每个修订版本到磁盘中,所以这个过程会非常快。如果愿意的话,你也可以通过 `--tree-filter` 选项来完成同样的任务。`git rm` 命令的 `--ignore-unmatch` 选项告诉命令:如果尝试删除的模式不存在时,不提示错误。最后,使用 `filter-branch` 选项来重写自 `7b30847` 提交以来的历史,也就是这个问题产生的地方。否则,这个命令会从最旧的提交开始,这将会花费许多不必要的时间。 + +你的历史中将不再包含对那个文件的引用。不过,你的引用日志和你在 `.git/refs/original` 通过 `filter-branch` 选项添加的新引用中还存有对这个文件的引用,所以你必须移除它们然后重新打包数据库。在重新打包前需要移除任何包含指向那些旧提交的指针的文件: ```shell $ rm -Rf .git/refs/original @@ -240,7 +279,9 @@ Compressing objects: 100% (11/11), done. Writing objects: 100% (15/15), done. Total 15 (delta 1), reused 12 (delta 0) ``` + 让我们看看你省了多少空间。 + ```shell $ git count-objects -v count: 11 @@ -252,7 +293,9 @@ prune-packable: 0 garbage: 0 size-garbage: 0 ``` -打包的仓库大小下降到了 8K,比 5MB 好很多。 可以从 size 的值看出,这个大文件还在你的松散对象中,并没有消失;但是它不会在推送或接下来的克隆中出现,这才是最重要的。 如果真的想要删除它,可以通过有`--expire`选项的`git prune`命令来完全地移除那个对象: + +打包的仓库大小下降到了 8K,比 5MB 好很多。可以从 size 的值看出,这个大文件还在你的松散对象中,并没有消失;但是它不会在推送或接下来的克隆中出现,这才是最重要的。如果真的想要删除它,可以通过有 `--expire` 选项的 `git prune` 命令来完全地移除那个对象: + ```shell $ git prune --expire now $ git count-objects -v @@ -264,4 +307,5 @@ size-pack: 8 prune-packable: 0 garbage: 0 size-garbage: 0 -``` \ No newline at end of file +``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/8. \347\216\257\345\242\203\345\217\230\351\207\217.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/8. \347\216\257\345\242\203\345\217\230\351\207\217.md" index fc1a5d4fb4632f869b286f96395e6a5f9842112c..57e8d5865a08e9653ee61cd011f1a52577bfcdcc 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/8. \347\216\257\345\242\203\345\217\230\351\207\217.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\206\205\351\203\250\345\216\237\347\220\206/8. \347\216\257\345\242\203\345\217\230\351\207\217.md" @@ -2,93 +2,89 @@ title: 环境变量 permalink: /git-tutorial/environment-variables --- + 我之前以为 Git 环境变量就是 path 里配置的那个系统变量路径。 -就是在执行 Git 命令会提示“不是内部或外部命令,也不是可运行的程序”的时候,去系统属性里将 path 添加一个 Git 路径`C:\Program Files\Git\cmd;` +就是在执行 Git 命令会提示“不是内部或外部命令,也不是可运行的程序”的时候,去系统属性里将 path 添加一个 Git 路径 `C:\Program Files\Git\cmd;`。 ## 全局行为 像通常的程序一样,Git 的常规行为依赖于环境变量。 -`GIT_EXEC_PATH`决定 Git 到哪找它的子程序 (像`git-commit`,`git-diff`等等)。 +`GIT_EXEC_PATH` 决定 Git 到哪找它的子程序 (像 `git-commit`、`git-diff` 等等)。 -你可以用`git --exec-path`来查看当前设置。 +你可以用 `git --exec-path` 来查看当前设置。 ![图片](./../../../.vuepress/public/images/8xIXzoqx8i8Yup4s.png) -通常不会考虑修改`HOME`这个变量(太多其它东西都依赖它),这是 Git 查找全局配置文件的地方。 +通常不会考虑修改 `HOME` 这个变量(太多其它东西都依赖它),这是 Git 查找全局配置文件的地方。 -`PREFIX`也类似,除了用于系统级别的配置。 Git 在`$PREFIX/etc/gitconfig`查找此文件。 +`PREFIX` 也类似,除了用于系统级别的配置。Git 在 `$PREFIX/etc/gitconfig` 查找此文件。 -如果设置了`GIT_CONFIG_NOSYSTEM`,就禁用系统级别的配置文件。 这在系统配置影响了你的命令,而你又无权限修改的时候很有用。 +如果设置了 `GIT_CONFIG_NOSYSTEM`,就禁用系统级别的配置文件。这在系统配置影响了你的命令,而你又无权限修改的时候很有用。 -`GIT_PAGER`控制在命令行上显示多页输出的程序。 如果这个没有设置,就会用`PAGER`。 +`GIT_PAGER` 控制在命令行上显示多页输出的程序。如果这个没有设置,就会用 `PAGER`。 -`GIT_EDITOR`当用户需要编辑一些文本(比如提交信息)时, Git 会启动这个编辑器。 如果没设置,就会用`EDITOR`。 +`GIT_EDITOR` 当用户需要编辑一些文本(比如提交信息)时,Git 会启动这个编辑器。如果没设置,就会用 `EDITOR`。 ## 版本库位置 Git 用了几个变量来确定它如何与当前版本库交互。 -`GIT_DIR`是`.git`目录的位置。 如果这个没有设置, Git 会按照目录树逐层向上查找`.git`目录,直到到达`~`或`/`。 +`GIT_DIR` 是 `.git` 目录的位置。如果这个没有设置,Git 会按照目录树逐层向上查找 `.git` 目录,直到到达 `~` 或 `/`。 -`GIT_CEILING_DIRECTORIES`控制查找`.git`目录的行为。 如果你访问加载很慢的目录(如那些磁带机上的或通过网络连接访问的),你可能会想让 Git 早点停止尝试,尤其是 shell 构建时调用了 Git 。 +`GIT_CEILING_DIRECTORIES` 控制查找 `.git` 目录的行为。如果你访问加载很慢的目录(如那些磁带机上的或通过网络连接访问的),你可能会想让 Git 早点停止尝试,尤其是 shell 构建时调用了 Git 。 -`GIT_WORK_TREE`是非空版本库的工作目录的根路径。 如果指定了`--git-dir`或`GIT_DIR`但未指定`--work-tree`、`GIT_WORK_TREE`或`core.worktree`,那么当前工作目录就会视作工作树的顶级目录。 +`GIT_WORK_TREE` 是非空版本库的工作目录的根路径。如果指定了 `--git-dir` 或 `GIT_DIR` 但未指定 `--work-tree`、`GIT_WORK_TREE` 或 `core.worktree`,那么当前工作目录就会视作工作树的顶级目录。 -`GIT_INDEX_FILE`是索引文件的路径(只有非空版本库有)。 +`GIT_INDEX_FILE` 是索引文件的路径(只有非空版本库有)。 -`GIT_OBJECT_DIRECTORY`用来指定`.git/objects`目录的位置。 +`GIT_OBJECT_DIRECTORY` 用来指定 `.git/objects` 目录的位置。 -`GIT_ALTERNATE_OBJECT_DIRECTORIES`一个冒号分割的列表(格式类似`/dir/one:/dir/two:…`)用来告诉 Git 到哪里去找不在`GIT_OBJECT_DIRECTORY`目录中的对象。 如果你有很多项目有相同内容的大文件,这个可以用来避免存储过多备份。 +`GIT_ALTERNATE_OBJECT_DIRECTORIES` 一个冒号分割的列表(格式类似 `/dir/one:/dir/two:…`)用来告诉 Git 到哪里去找不在 `GIT_OBJECT_DIRECTORY` 目录中的对象。如果你有很多项目有相同内容的大文件,这个可以用来避免存储过多备份。 ## 路径规则 -所谓 “pathspec” 是指你在 Git 中如何指定路径,包括通配符的使用。 它们会在`.gitignore`文件中用到,命令行里也会用到(`git add *.c`)。 +所谓 “pathspec” 是指你在 Git 中如何指定路径,包括通配符的使用。它们会在 `.gitignore` 文件中用到,命令行里也会用到(`git add *.c`)。 -`GIT_GLOB_PATHSPECS`和`GIT_NOGLOB_PATHSPECS`控制通配符在路径规则中的默认行为。 如果`GIT_GLOB_PATHSPECS`设置为 1, 通配符表现为通配符(这是默认设置); 如果`GIT_NOGLOB_PATHSPECS`设置为 1,通配符仅匹配字面。意思是`*.c`只会匹配**文件名是**“*.c” 的文件,而不是以`.c`结尾的文件。 你可以在各个路径规范中用`:(glob)`或`:(literal)`开头来覆盖这个配置,如`:(glob)*.c`。 +`GIT_GLOB_PATHSPECS` 和 `GIT_NOGLOB_PATHSPECS` 控制通配符在路径规则中的默认行为。如果 `GIT_GLOB_PATHSPECS` 设置为 1,通配符表现为通配符(这是默认设置);如果 `GIT_NOGLOB_PATHSPECS` 设置为 1,通配符仅匹配字面。意思是 `*.c` 只会匹配文件名是 `*.c` 的文件,而不是以 `.c` 结尾的文件。你可以在各个路径规范中用 `:(glob)` 或 `:(literal)` 开头来覆盖这个配置,如 `:(glob)*.c`。 -`GIT_LITERAL_PATHSPECS`禁用上面的两种行为;通配符将不能用,前缀覆盖也不能用。 +`GIT_LITERAL_PATHSPECS` 禁用上面的两种行为;通配符将不能用,前缀覆盖也不能用。 -`GIT_ICASE_PATHSPECS`让所有的路径规范忽略大小写。 +`GIT_ICASE_PATHSPECS` 让所有的路径规范忽略大小写。 ## 提交 -Git 提交对象的创建通常最后是由`git-commit-tree`来完成,`git-commit-tree`用这些环境变量作主要的信息源。 仅当这些值不存在才回退到预置的值。 - -`GIT_AUTHOR_NAME`是 “author” 字段的可读名字。 - -`GIT_AUTHOR_EMAIL`是 “author” 字段的邮件。 - -`GIT_AUTHOR_DATE`是 “author” 字段的时间戳。 - -`GIT_COMMITTER_NAME`是 “committer” 字段的可读名字。 +Git 提交对象的创建通常最后是由 `git-commit-tree` 来完成,`git-commit-tree` 用这些环境变量作主要的信息源。仅当这些值不存在才回退到预置的值。 -`GIT_COMMITTER_EMAIL`是 “committer” 字段的邮件。 +- `GIT_AUTHOR_NAME`是 “author” 字段的可读名字。 +- `GIT_AUTHOR_EMAIL`是 “author” 字段的邮件。 +- `GIT_AUTHOR_DATE`是 “author” 字段的时间戳。 +- `GIT_COMMITTER_NAME`是 “committer” 字段的可读名字。 +- `GIT_COMMITTER_EMAIL`是 “committer” 字段的邮件。 +- `GIT_COMMITTER_DATE`是 “committer” 字段的时间戳。 -`GIT_COMMITTER_DATE`是 “committer” 字段的时间戳。 - -如果`user.email`没有配置, 就会用到`EMAIL`指定的邮件地址。 如果**这个**也没有设置, Git 继续回退使用系统用户和主机名。 +如果 `user.email` 没有配置,就会用到 `EMAIL` 指定的邮件地址。如果**这个**也没有设置,Git 继续回退使用系统用户和主机名。 ## 网络 -Git 使用`curl`库通过 HTTP 来完成网络操作, 所以`GIT_CURL_VERBOSE`告诉 Git 显示所有由那个库产生的消息。 这跟在命令行执行`curl -v`差不多。 +Git 使用 `curl` 库通过 HTTP 来完成网络操作,所以 `GIT_CURL_VERBOSE` 告诉 Git 显示所有由那个库产生的消息。这跟在命令行执行 `curl -v` 差不多。 -`GIT_SSL_NO_VERIFY`告诉 Git 不用验证 SSL 证书。 这在有些时候是需要的, 例如你用一个自己签名的证书通过 HTTPS 来提供 Git 服务, 或者你正在搭建 Git 服务器,还没有安装完全的证书。 +`GIT_SSL_NO_VERIFY` 告诉 Git 不用验证 SSL 证书。这在有些时候是需要的,例如你用一个自己签名的证书通过 HTTPS 来提供 Git 服务,或者你正在搭建 Git 服务器,还没有安装完全的证书。 -如果 Git 操作在网速低于`GIT_HTTP_LOW_SPEED_LIMIT`字节/秒,并且持续`GIT_HTTP_LOW_SPEED_TIME`秒以上的时间,Git 会终止那个操作。 这些值会覆盖`http.lowSpeedLimit`和`http.lowSpeedTime`配置的值。 +如果 Git 操作在网速低于 `GIT_HTTP_LOW_SPEED_LIMIT` 字节/秒,并且持续 `GIT_HTTP_LOW_SPEED_TIME` 秒以上的时间,Git 会终止那个操作。这些值会覆盖 `http.lowSpeedLimit` 和 `http.lowSpeedTime` 配置的值。 -`GIT_HTTP_USER_AGENT`设置 Git 在通过 HTTP 通讯时用到的 user-agent。 默认值类似于`git/2.0.0`。 +`GIT_HTTP_USER_AGENT` 设置 Git 在通过 HTTP 通讯时用到的 user-agent。默认值类似于 `git/2.0.0`。 ## 比较和合并 -`GIT_DIFF_OPTS`这个有点起错名字了。 有效值仅支持`-u`或`--unified=`,用来控制在`git diff`命令中显示的内容行数。 +`GIT_DIFF_OPTS` 这个有点起错名字了。有效值仅支持 `-u` 或 `--unified=`,用来控制在 `git diff` 命令中显示的内容行数。 -`GIT_EXTERNAL_DIFF`用来覆盖`diff.external`配置的值。 如果设置了这个值, 当执行`git diff`时,Git 会调用该程序。 +`GIT_EXTERNAL_DIFF` 用来覆盖 `diff.external` 配置的值。如果设置了这个值,当执行 `git diff` 时,Git 会调用该程序。 -`GIT_DIFF_PATH_COUNTER`和`GIT_DIFF_PATH_TOTAL`对于`GIT_EXTERNAL_DIFF`或`diff.external`指定的程序有用。 前者表示在一系列文件中哪个是被比较的(从 1 开始),后者表示每批文件的总数。 +`GIT_DIFF_PATH_COUNTER` 和 `GIT_DIFF_PATH_TOTAL` 对于 `GIT_EXTERNAL_DIFF` 或 `diff.external` 指定的程序有用。 前者表示在一系列文件中哪个是被比较的(从 1 开始),后者表示每批文件的总数。 -`GIT_MERGE_VERBOSITY`控制递归合并策略的输出。 允许的值有下面这些: +`GIT_MERGE_VERBOSITY` 控制递归合并策略的输出。允许的值有下面这些: * 0 什么都不输出,除了可能会有一个错误信息。 * 1 只显示冲突。 @@ -101,12 +97,12 @@ Git 使用`curl`库通过 HTTP 来完成网络操作, 所以`GIT_CURL_VERBOSE` ## 调试 -想**真正地**知道 Git 正在做什么? Git 内置了相当完整的跟踪信息,你需要做的就是把它们打开。 这些变量的可用值如下: +想**真正地**知道 Git 正在做什么?Git 内置了相当完整的跟踪信息,你需要做的就是把它们打开。这些变量的可用值如下: -* “true”“1” 或 “2”——跟踪类别写到标准错误输出。 -* 以`/`开头的绝对路径——跟踪输出会被写到那个文件。 +* “true”、“1” 或 “2” —— 跟踪类别写到标准错误输出。 +* 以 `/` 开头的绝对路径 —— 跟踪输出会被写到那个文件。 -`GIT_TRACE`控制常规跟踪,它并不适用于特殊情况。 它跟踪的范围包括别名的展开和其他子程序的委托。 +`GIT_TRACE` 控制常规跟踪,它并不适用于特殊情况。它跟踪的范围包括别名的展开和其他子程序的委托。 ```shell $ GIT_TRACE=true git lga @@ -117,7 +113,9 @@ $ GIT_TRACE=true git lga 20:12:49.899217 run-command.c:341 trace: run_command: 'less' 20:12:49.899675 run-command.c:192 trace: exec: 'less' ``` -`GIT_TRACE_PACK_ACCESS`控制访问打包文件的跟踪信息。 第一个字段是被访问的打包文件,第二个是文件的偏移量: + +`GIT_TRACE_PACK_ACCESS` 控制访问打包文件的跟踪信息。第一个字段是被访问的打包文件,第二个是文件的偏移量: + ```shell $ GIT_TRACE_PACK_ACCESS=true git status 20:10:12.081397 sha1_file.c:2088 .git/objects/pack/pack-c3fa...291e.pack 12 @@ -130,7 +128,9 @@ On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean ``` -`GIT_TRACE_PACKET`打开网络操作包级别的跟踪信息。 + +`GIT_TRACE_PACKET` 打开网络操作包级别的跟踪信息。 + ```shell $ GIT_TRACE_PACKET=true git ls-remote origin 20:15:14.867043 pkt-line.c:46 packet: git< # service=git-upload-pack @@ -140,7 +140,9 @@ $ GIT_TRACE_PACKET=true git ls-remote origin 20:15:14.867094 pkt-line.c:46 packet: git< 36dc827bc9d17f80ed4f326de21247a5d1341fbc refs/heads/ah/doc-gitk-config # […] ``` -`GIT_TRACE_PERFORMANCE`控制性能数据的日志打印。 输出显示了每个`git`命令调用花费的时间。 + +`GIT_TRACE_PERFORMANCE` 控制性能数据的日志打印。输出显示了每个 `git` 命令调用花费的时间。 + ```shell $ GIT_TRACE_PERFORMANCE=true git gc 20:18:19.499676 trace.c:414 performance: 0.374835000 s: git command: 'git' 'pack-refs' '--all' '--prune' @@ -159,7 +161,9 @@ Checking connectivity: 170994, done. 20:18:25.232403 trace.c:414 performance: 0.001051000 s: git command: 'git' 'rerere' 'gc' 20:18:25.233159 trace.c:414 performance: 6.112217000 s: git command: 'git' 'gc' ``` -`GIT_TRACE_SETUP`显示 Git 发现的关于版本库和交互环境的信息。 + +`GIT_TRACE_SETUP` 显示 Git 发现的关于版本库和交互环境的信息。 + ```shell $ GIT_TRACE_SETUP=true git status 20:19:47.086765 trace.c:315 setup: git_dir: .git @@ -170,21 +174,23 @@ On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working directory clean ``` + ## 其它 -如果指定了`GIT_SSH`, Git 连接 SSH 主机时会用指定的程序代替`ssh`。 它会被用`$GIT_SSH [username@]host [-p ] `的命令方式调用。 这不是配置定制`ssh`调用方式的最简单的方法; 它不支持额外的命令行参数, 所以你必须写一个封装脚本然后让`GIT_SSH`指向它。 可能用`~/.ssh/config`会更简单。 +如果指定了 `GIT_SSH`,Git 连接 SSH 主机时会用指定的程序代替 `ssh`。它会被用 `$GIT_SSH [username@]host [-p ] ` 的命令方式调用。这不是配置定制 `ssh` 调用方式的最简单的方法;它不支持额外的命令行参数, 所以你必须写一个封装脚本然后让 `GIT_SSH` 指向它。可能用 `~/.ssh/config` 会更简单。 -`GIT_ASKPASS`覆盖了`core.askpass`配置。 这是 Git 需要向用户请求验证时用到的程序,它接受一个文本提示作为命令行参数,并在`stdout`中返回应答。 +`GIT_ASKPASS` 覆盖了 `core.askpass` 配置。这是 Git 需要向用户请求验证时用到的程序,它接受一个文本提示作为命令行参数,并在 `stdout` 中返回应答。 -`GIT_NAMESPACE`控制有命令空间的引用的访问,与`--namespace`标志是相同的。 这主要在服务器端有用, 如果你想在一个版本库中存储单个版本库的多个 fork, 只要保持引用是隔离的就可以。 +`GIT_NAMESPACE` 控制有命令空间的引用的访问,与 `--namespace` 标志是相同的。这主要在服务器端有用,如果你想在一个版本库中存储单个版本库的多个 fork,只要保持引用是隔离的就可以。 -`GIT_FLUSH`强制 Git 在向标准输出增量写入时使用没有缓存的 I/O。 设置为 1 让 Git 刷新更多, 设置为 0 则使所有的输出被缓存。 默认值(若此变量未设置)是根据活动和输出模式的不同选择合适的缓存方案。 +`GIT_FLUSH` 强制 Git 在向标准输出增量写入时使用没有缓存的 I/O。设置为 1 让 Git 刷新更多,设置为 0 则使所有的输出被缓存。默认值(若此变量未设置)是根据活动和输出模式的不同选择合适的缓存方案。 -`GIT_REFLOG_ACTION`让你可以指定描述性的文字写到 reflog 中。 这有个例子: +`GIT_REFLOG_ACTION` 让你可以指定描述性的文字写到 reflog 中。这有个例子: ```shell $ GIT_REFLOG_ACTION="my action" git commit --allow-empty -m 'my message' [master 9e3d55a] my message $ git reflog -1 9e3d55a HEAD@{0}: my action: my message -``` \ No newline at end of file +``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/1. \351\200\211\346\213\251\344\277\256\350\256\242\347\211\210\346\234\254.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/1. \351\200\211\346\213\251\344\277\256\350\256\242\347\211\210\346\234\254.md" index 19f68a5dfbaee2ad9070cbd16809770f628966c3..ea9cca862593cd4208d7a736c059855d9c0cbfa6 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/1. \351\200\211\346\213\251\344\277\256\350\256\242\347\211\210\346\234\254.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/1. \351\200\211\346\213\251\344\277\256\350\256\242\347\211\210\346\234\254.md" @@ -2,13 +2,14 @@ title: 选择修订版本 permalink: /git-tutorial/git-log --- + Git 允许使用者通过几种方法在指定或者一定范围内的提交,分配提交,分组提交。 ## 指明单次提交 -使用简明的 SHA-1 ( hash 值)指明单个提交: git show [SHA-1值] +使用简明的 SHA-1(hash 值)指明单个提交:`git show [SHA-1值]`。 -获取 SHA-1 值(hash值): +获取 SHA-1 值(hash 值): ```shell $ git log @@ -21,13 +22,17 @@ Author: QAQSarah <0979@example.com> Date: Tue Aug 25 22:23:33 2020 +0800 1 ``` -如果你在 git log 后加上 --abbrev-commit 参数,输出结果里就会显示简短且唯一的值;默认使用七个字符,不过有时为了避免 SHA-1 的歧义,会增加字符数: + +如果你在 `git log` 后加上 `--abbrev-commit` 参数,输出结果里就会显示简短且唯一的值;默认使用七个字符,不过有时为了避免 SHA-1 的歧义,会增加字符数: + ```shell $ git log --abbrev-commit --pretty=oneline b830542 (HEAD -> master) 2 947d964 1 ``` -假如这个提交的SHA-1的值是 974d...,则: + +假如这个提交的 SHA-1 的值是 `974d...`,则: + ```shell $ git show 947d9649b7a2c028050da2fa7aafef8f67cc9997 commit 947d9649b7a2c028050da2fa7aafef8f67cc9997 @@ -38,41 +43,49 @@ diff --git a/ss.txt b/ss.txt new file mode 100644 index 0000000..e69de29 ``` + ## 分支引用 -显示一个分支的最后一次提交的对象:git show [分支名] +显示一个分支的最后一次提交的对象:`git show [分支名]`。 -指明一次提交最直接的方法是有一个指向它的分支引用。例如,你想要查看一个分支的最后一次提交的对象,假设 topic1 分支指向 947d.. ,那么以下的命令是等价的: +指明一次提交最直接的方法是有一个指向它的分支引用。例如,你想要查看一个分支的最后一次提交的对象,假设 topic1 分支指向 `947d...` ,那么以下的命令是等价的。 ```shell $ git show 947d9649b7a2c028050da2fa7aafef8f67cc9997 $ git show topic1 ``` + 如果你想知道某个分支指向哪个特定的 SHA-1,或者想看任何一个例子中被简写的 SHA-1 ,你可以使用一个叫做 rev-parse 的 Git 探测工具。 + ```shell $ git rev-parse topic1 947d9649b7a2c028050da2fa7aafef8f67cc9997 ``` + ## 引用日志 -引用日志里的简称指明单个提交:git show HEAD@{n} +引用日志里的简称指明单个提交:`git show HEAD@{n}`。 -当使用 Git 工作时,Git会在后台保存一个引用日志( reflog ),引用日志记录了最近一次的HEAD和分支引用所指向的历史. +当使用 Git 工作时,Git 会在后台保存一个引用日志(reflog),引用日志记录了最近一次的 HEAD 和分支引用所指向的历史。 -git reflog : 查看引用日志 +git reflog:查看引用日志 ```shell $ git reflog b830542 (HEAD -> master) HEAD@{0}: commit: 2 947d964 HEAD@{1}: commit (initial): 1 ``` -每当你的 HEAD 所指向的位置发生了变化,Git 就会将这个信息存储到引用日志这个历史记录里。 通过这些数据,你可以很方便地获取之前的提交历史。 如果你想查看仓库中 HEAD 在五次前的所指向的提交,**你可以使用 @{n} 来引用 reflog 中输出的提交记录**。 + +每当你的 HEAD 所指向的位置发生了变化,Git 就会将这个信息存储到引用日志这个历史记录里。 通过这些数据,你可以很方便地获取之前的提交历史。 如果你想查看仓库中 HEAD 在五次前的所指向的提交,**你可以使用 `@{n}` 来引用 reflog 中输出的提交记录**。 + ```shell -$ git show HEAD@{5}` +$ git show HEAD@{5} ``` -例子如下: + +例子如下: + ```shell -//指定次数超过提交的次数 +# 指定次数超过提交的次数 $ git show HEAD@{2} fatal: Log for 'HEAD' only has 2 entries. $ git show HEAD@{1} @@ -84,7 +97,9 @@ diff --git a/ss.txt b/ss.txt new file mode 100644 index 0000000..e69de29 ``` + 你同样可以使用这个语法来查看某个分支在一定时间前的位置。 例如,查看你的 master 分支在昨天的时候指向了哪个提交,你可以输入: + ```shell $ git show master@{yesterday} commit b830542ac6953c0bf1c49fa5ae00a9be239ac6ca (HEAD -> master) @@ -95,8 +110,10 @@ diff --git a/ss.txt b/ss.txt deleted file mode 100644 index e69de29..0000000 ``` + 显示昨天该分支的顶端指向了哪个提交。 这个方法只对还在你引用日志里的数据有用,所以不能用来查好几个月之前的提交。 -也可以运行 git log -g 来查看类似于 git log 输出格式的引用日志信息: + +也可以运行 `git log -g` 来查看类似于 `git log` 输出格式的引用日志信息: ```shell $ git log -g master commit @@ -113,12 +130,14 @@ Author: Scott Chacon Date: Thu Dec 11 15:08:43 2019-0800 Merge commit 'phedders/rdocs' ``` + 值得注意的是,引用日志只存在于本地仓库,一个记录你在你自己的仓库里做过什么的日志。 其他人拷贝的仓库里的引用日志不会和你的相同;而你新克隆一个仓库的时候,引用日志是空的,因为你在仓库里还没有操作。 + ## 祖先引用 -指明某次提交的父提交: `git show HEAD^` 与 `git show HEAD~` +指明某次提交的父提交:`git show HEAD^` 与 `git show HEAD~`。 -如果你在引用的尾部加上一个 ^(脱字符),Git转换其解析为该引用的上一个提交。假设你的提交历史是: +如果你在引用的尾部加上一个 `^`(脱字符),Git 转换其解析为该引用的上一个提交。假设你的提交历史是: ```shell $ git log --pretty=format:'%h %s' --graph @@ -126,7 +145,9 @@ $ git log --pretty=format:'%h %s' --graph * b830542 2 * 947d964 1 ``` -你也可以在 ^ 后面添加一个数字——例如 b830542^1 代表 “b830542 的第一父提交” 这个语法只适用于合并(merge)的提交,因为合并提交会有多个父提交。 第一父提交是你合并时所在分支,而第二父提交是你所合并的分支: + +你也可以在 `^` 后面添加一个数字 —— 例如 b830542^1 代表 “b830542 的第一父提交” 这个语法只适用于合并(merge)的提交,因为合并提交会有多个父提交。 第一父提交是你合并时所在分支,而第二父提交是你所合并的分支: + ```shell $ git show b830542^ commit 947d9649b7a2c028050da2fa7aafef8f67cc9997 @@ -137,7 +158,9 @@ diff --git a/ss.txt b/ss.txt new file mode 100644 index 0000000..e69de29 ``` -另一种指明祖先提交的方法是 `~`。 同样是指向第一父提交,因此 `HEAD~` 和 `HEAD^` 是等价的。 而区别在于你在后面加数字的时候。 `HEAD~2` 代表 “第一父提交的第一父提交”,也就是 “祖父提交”例如,在之前的列出的提交历史中,`HEAD~3` 就是 + +另一种指明祖先提交的方法是 `~`。 同样是指向第一父提交,因此 `HEAD~` 和 `HEAD^` 是等价的。而区别在于你在后面加数字的时候。`HEAD~2` 代表 “第一父提交的第一父提交”,也就是 “祖父提交”例如,在之前的列出的提交历史中,`HEAD~3` 就是: + ```shell $ git show HEAD~3 commit b830542ac6953c0bf1c49fa5ae00a9be239ac6ca (test) @@ -148,7 +171,9 @@ diff --git a/ss.txt b/ss.txt deleted file mode 100644 index e69de29..0000000 ``` -也可以写成 HEAD^^^,也是第一父提交的第一父提交的第一父提交: + +也可以写成 `HEAD^^^`,也是第一父提交的第一父提交的第一父提交: + ```shell $ git show HEAD^^^ commit b830542ac6953c0bf1c49fa5ae00a9be239ac6ca (test) @@ -159,15 +184,16 @@ diff --git a/ss.txt b/ss.txt deleted file mode 100644 index e69de29..0000000 ``` + 你也可以组合使用这两个语法 —— 你可以通过 `HEAD~3^2` 来取得之前引用的第二父提交(假设它是一个合并提交)。 ## 指明范围提交 -### **1.双点** +### 1. 双点 找出可从一个分支获得而不能从另一个分支获得的提交。例如,你有如下的提交历史示例范围选择的历史。 -git log test..master  (意思是“所有可从master分支中获得而不能从test分支中获得的提交”。) +`git log test..master`(意思是“所有可从 master 分支中获得而不能从 test 分支中获得的提交”。) ```shell $ git log test..master @@ -184,7 +210,9 @@ Author: QAQSarah <0979@example.com> Date: Mon Aug 31 23:00:31 2020 +0800 test1 ``` -git log master..test(反过来所有在 test 而不在 master 中的分支) + +`git log master..test`(反过来所有在 test 而不在 master 中的分支) + ```shell $ git log master..test commit 841ce6e314311f32a2738768b3bab73c9062a0e3 (HEAD -> test) @@ -193,23 +221,30 @@ Date: Mon Aug 31 23:47:56 2020 +0800 test-v ``` -### **2.多点** +### 2. 多点 在多个分支筛选提交。 -例如查看这些提交是被包含在某些分支中的一个,但是不在你当前的分支上。在任意引用前加上 ^ 字符或者 --not,来指明你不希望提交被包含其中的分支因此下列三个命令是等价的: +例如查看这些提交是被包含在某些分支中的一个,但是不在你当前的分支上。在任意引用前加上 `^` 字符或者 `--not`,来指明你不希望提交被包含其中的分支因此下列三个命令是等价的: ```shell -git log refA..refB <=>git log ^refA..refB <=> git log refB - -not refA +git log refA..refB +git log ^refA..refB +git log refB --not refA ``` + 多分支: + ```shell -git log refA refB ^refC <=> git log refA refB - -not refC +git log refA refB ^refC +git log refA refB --not refC ``` -### **3.三点**: + +### 3. 三点 这个语法可以选择出被两个引用之一包含但又不被其中同时包含的提交。再看看之前双点示例中的提交历史。 -看master或者test中包含的但不是两个共有的提交,你可以执行:(在两个分支中被单个分支包含但又不被同时包含 :) + +看 master 或者 test 中包含的但不是两个共有的提交,你可以执行:(在两个分支中被单个分支包含但又不被同时包含) ```shell $ git log master...test @@ -230,3 +265,4 @@ Author: QAQSarah <0979@example.com> Date: Mon Aug 31 23:00:31 2020 +0800 test1 ``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/10. \345\255\220\346\250\241\345\235\227.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/10. \345\255\220\346\250\241\345\235\227.md" index 21aae2e0c80375a0ed1255e25d3d98555dbad221..dc608f66c039ea4809a281a9bddcd66c156561d5 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/10. \345\255\220\346\250\241\345\235\227.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/10. \345\255\220\346\250\241\345\235\227.md" @@ -3,7 +3,7 @@ title: 子模块 permalink: /git-tutorial/git-submodule --- -`git submodule` + ## 开始使用 @@ -13,9 +13,9 @@ permalink: /git-tutorial/git-submodule 我们将要演示如何在一个被分成一个主项目与几个子项目的项目上开发。 -我们首先将一个已存在的 Git 仓库添加为正在工作的仓库的子模块。 你可以通过在`git submodule add`命令后面加上想要跟踪的项目的相对或绝对 URL 来添加新的子模块。 +我们首先将一个已存在的 Git 仓库添加为正在工作的仓库的子模块。 你可以通过在 `git submodule add` 命令后面加上想要跟踪的项目的相对或绝对 URL 来添加新的子模块。 -首先新建了一个远程仓库当做子模块,然后在主项目上使用命令添加子模块 +首先新建了一个远程仓库当做子模块,然后在主项目上使用命令添加子模块: ```shell Administrator@F69J2GKVB3UPVZ7 MINGW64 /g/test/fake-project (master) @@ -28,8 +28,10 @@ Unpacking objects: 100% (3/3), done. warning: LF will be replaced by CRLF in .gitmodules. The file will have its original line endings in your working directory. ``` -默认情况下,子模块会将子项目放到一个与仓库同名的目录中`git_submodule`。 如果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径。 -如果这时运行`git status`,你会注意到几件事。 + +默认情况下,子模块会将子项目放到一个与仓库同名的目录中 `git_submodule`。 如果你想要放到其他地方,那么可以在命令结尾添加一个不同的路径。 + +如果这时运行 `git status`,你会注意到几件事。 ```shell $ git status @@ -42,7 +44,9 @@ Changes to be committed:         new file:   .gitmodules         new file:   git_submodule ``` -首先应当注意到新的`.gitmodules`文件。 该配置文件保存了项目 URL 与已经拉取的本地目录之间的映射: + +首先应当注意到新的 `.gitmodules` 文件。该配置文件保存了项目 URL 与已经拉取的本地目录之间的映射: + ![图片](./../../../.vuepress/public/images/Dy5f6kKzNebfru3u.png) ```shell @@ -50,8 +54,10 @@ Changes to be committed: path = git_submodule url = https://gitee.com/willcoder/git_submodule.git ``` -如果有多个子模块,该文件中就会有多条记录。 要重点注意的是,该文件也像`.gitignore`文件一样受到(通过)版本控制。 它会和该项目的其他部分一同被拉取推送。 这就是克隆该项目的人知道去哪获得子模块的原因。 -在`git status`输出中列出的另一个是项目文件夹记录。 如果你运行`git diff`,会看到类似下面的信息: + +如果有多个子模块,该文件中就会有多条记录。要重点注意的是,该文件也像 `.gitignore` 文件一样受到(通过)版本控制。它会和该项目的其他部分一同被拉取推送。这就是克隆该项目的人知道去哪获得子模块的原因。 + +在 `git status` 输出中列出的另一个是项目文件夹记录。如果你运行 `git diff`,会看到类似下面的信息: ```shell $ git diff --cached git_submodule @@ -63,8 +69,10 @@ index 0000000..0c7ce50 @@ -0,0 +1 @@ +Subproject commit 0c7ce502e3c47b30e02e08c1ff015660ff3bed45 ``` -虽然`git_submodule`是工作目录中的一个子目录,但 Git 还是会将它视作一个子模块。当你不在那个目录中时,Git 并不会跟踪它的内容, 而是将它看作子模块仓库中的某个具体的提交。 -如果你想看到更漂亮的差异输出,可以给`git diff`传递`--submodule`选项。 + +虽然 `git_submodule` 是工作目录中的一个子目录,但 Git 还是会将它视作一个子模块。当你不在那个目录中时,Git 并不会跟踪它的内容, 而是将它看作子模块仓库中的某个具体的提交。 + +如果你想看到更漂亮的差异输出,可以给 `git diff` 传递 `--submodule` 选项。 ```shell $ git diff --cached --submodule @@ -79,7 +87,9 @@ index 0000000..7345b56 +       url = https://gitee.com/willcoder/git_submodule.git Submodule git_submodule 0000000...0c7ce50 (new submodule) ``` + 当你提交时,会看到类似下面的信息: + ```shell $ git commit -am 'add git_submodules' [master 8738267] add git_submodules @@ -87,15 +97,18 @@ $ git commit -am 'add git_submodules'  create mode 100644 .gitmodules  create mode 160000 git_submodule ``` -注意`git_submodule`记录的`160000`模式。 这是 Git 中的一种特殊模式,它本质上意味着你是将一次提交记作一项目录记录的,而非将它记录成一个子目录或者一个文件。 + +注意 `git_submodule` 记录的 `160000` 模式。这是 Git 中的一种特殊模式,它本质上意味着你是将一次提交记作一项目录记录的,而非将它记录成一个子目录或者一个文件。 + 最后,推送这些更改: ```shell $ git push origin master ``` + ## 克隆含有子模块的项目 -接下来我们将会克隆一个含有子模块的项目。 当你在克隆这样的项目时,默认会包含该子模块目录,但其中还没有任何文件: +接下来我们将会克隆一个含有子模块的项目。当你在克隆这样的项目时,默认会包含该子模块目录,但其中还没有任何文件: ```shell $ git clone https://gitee.com/willcoder/fake-project.git @@ -109,9 +122,10 @@ $ cd fake-project/git_submodule/ $ ll total 0 ``` + ![图片](./../../../.vuepress/public/images/GGqVzOx2U9qX6Lgf.png) -其中有`git_submodule`目录,不过是空的。此时必须运行两个命令:`git submodule init`用来初始化本地配置文件,而`git submodule update`则从该项目中抓取所有数据并检出父项目中列出的合适的提交。 +其中有 `git_submodule` 目录,不过是空的。此时必须运行两个命令:`git submodule init` 用来初始化本地配置文件,而 `git submodule update` 则从该项目中抓取所有数据并检出父项目中列出的合适的提交。 ```shell $ git submodule init @@ -120,8 +134,10 @@ $ git submodule update Cloning into 'G:/test2/fake-project/git_submodule'... Submodule path 'git_submodule': checked out '0c7ce502e3c47b30e02e08c1ff015660ff3bed45' ``` -现在`git_submodule`子目录是处在和之前提交时相同的状态了。 -不过还有更简单一点的方式。 如果给`git clone`命令传递`--recurse-submodules`选项,它就会自动初始化并更新仓库中的每一个子模块, 包括可能存在的嵌套子模块。 + +现在 `git_submodule` 子目录是处在和之前提交时相同的状态了。 + +不过还有更简单一点的方式。 如果给 `git clone` 命令传递 `--recurse-submodules` 选项,它就会自动初始化并更新仓库中的每一个子模块,包括可能存在的嵌套子模块。 ```shell $ git clone --recurse-submodules https://gitee.com/willcoder/fake-project.git @@ -138,7 +154,9 @@ remote: Counting objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Submodule path 'git_submodule': checked out '0c7ce502e3c47b30e02e08c1ff015660ff3bed45' ``` -如果你已经克隆了项目但忘记了`--recurse-submodules`,那么可以运行`git submodule update --init`将`git submodule init`和`git submodule update`合并成一步。如果还要初始化、抓取并检出任何嵌套的子模块, 请使用简明的`git submodule update --init --recursive`。 + +如果你已经克隆了项目但忘记了 `--recurse-submodules`,那么可以运行 `git submodule update --init` 将 `git submodule init` 和 `git submodule update` 合并成一步。如果还要初始化、抓取并检出任何嵌套的子模块, 请使用简明的 `git submodule update --init --recursive`。 + ## 在包含子模块的项目上工作 现在我们有一份包含子模块的项目副本,我们将会同时在主项目和子模块项目上与队员协作。 @@ -147,7 +165,7 @@ Submodule path 'git_submodule': checked out '0c7ce502e3c47b30e02e08c1ff015660ff3 在项目中使用子模块的最简模型,就是只使用子项目并不时地获取更新,而并不在你的检出中进行任何更改。 我们来看一个简单的例子。 -如果想要在子模块中查看新工作,可以进入到目录中运行`git fetch`与`git merge`,合并上游分支来更新本地代码。 +如果想要在子模块中查看新工作,可以进入到目录中运行 `git fetch` 与 `git merge`,合并上游分支来更新本地代码。 ```shell $ git fetch @@ -163,15 +181,19 @@ Fast-forward  my_submodule.txt | 3 ++-  1 file changed, 2 insertions(+), 1 deletion(-) ``` -如果你现在返回到主项目并运行`git diff --submodule`,就会看到子模块被更新的同时获得了一个包含新添加提交的列表。 如果你不想每次运行`git diff`时都输入`--submodle`,那么可以将`diff.submodule`设置为 “log” 来将其作为默认行为。 + +如果你现在返回到主项目并运行 `git diff --submodule`,就会看到子模块被更新的同时获得了一个包含新添加提交的列表。 如果你不想每次运行 `git diff` 时都输入 `--submodle`,那么可以将 `diff.submodule` 设置为 “log” 来将其作为默认行为。 + ```shell $ git config --global diff.submodule log $ git diff Submodule git_submodule 0c7ce50..a5cbd40:   > update my_submodule.txt. ``` + 如果在此时提交,那么你会将子模块锁定为其他人更新时的新代码。 -如果你不想在子目录中手动抓取与合并,那么还有种更容易的方式。 运行`git submodule update --remote`,Git 将会进入子模块然后抓取并更新。 + +如果你不想在子目录中手动抓取与合并,那么还有种更容易的方式。运行 `git submodule update --remote`,Git 将会进入子模块然后抓取并更新。 ```shell $ git submodule update --remote git_submodule @@ -183,7 +205,9 @@ From https://gitee.com/willcoder/git_submodule    a5cbd40..a7597da  master     -> origin/master Submodule path 'git_submodule': checked out 'a7597dad4a94bec59bd44d36e53939add9735ada' ``` -此命令默认会假定你想要更新并检出子模块仓库的`master`分支。 不过你也可以设置为想要的其他分支。 例如,你想要子模块跟踪仓库的 “stable” 分支,那么既可以在`.gitmodules`文件中设置 (这样其他人也可以跟踪它),也可以只在本地的`.git/config`文件中设置。 让我们在`.gitmodules`文件中设置它: + +此命令默认会假定你想要更新并检出子模块仓库的 `master` 分支。 不过你也可以设置为想要的其他分支。例如,你想要子模块跟踪仓库的 “stable” 分支,那么既可以在 `.gitmodules` 文件中设置 (这样其他人也可以跟踪它),也可以只在本地的 `.git/config` 文件中设置。让我们在 `.gitmodules` 文件中设置它: + ```shell $ git config -f .gitmodules submodule.git_submodule.branch stable $ git submodule update --remote @@ -196,8 +220,10 @@ From https://gitee.com/willcoder/git_submodule  * [new branch]      stable     -> origin/stable Submodule path 'git_submodule': checked out 'b2f53efebee60cf5b2092f911bf170e338c3acd1' ``` -如果不用`-f .gitmodules`选项,那么它只会为你做修改。但是在仓库中保留跟踪信息更有意义一些,因为其他人也可以得到同样的效果。 -这时我们运行`git status`,Git 会显示子模块中有“新提交”。 + +如果不用 `-f .gitmodules` 选项,那么它只会为你做修改。但是在仓库中保留跟踪信息更有意义一些,因为其他人也可以得到同样的效果。 + +这时我们运行 `git status`,Git 会显示子模块中有“新提交”。 ```shell $ git status @@ -210,7 +236,9 @@ Changes not staged for commit:         modified:   git_submodule (new commits) no changes added to commit (use "git add" and/or "git commit -a") ``` -如果你设置了配置选项`status.submodulesummary`,Git 也会显示你的子模块的更改摘要: + +如果你设置了配置选项 `status.submodulesummary`,Git 也会显示你的子模块的更改摘要: + ```shell $ git config status.submodulesummary 1 $ git status @@ -226,7 +254,9 @@ Submodules changed but not updated:   > update my_submodule.txt. no changes added to commit (use "git add" and/or "git commit -a") ``` -这时如果运行`git diff`,可以看到我们修改了 .gitmodules 文件,同时还有几个已拉取的提交需要提交到我们自己的子模块项目中。 + +这时如果运行 `git diff`,可以看到我们修改了 .gitmodules 文件,同时还有几个已拉取的提交需要提交到我们自己的子模块项目中。 + ```shell $ git diff warning: LF will be replaced by CRLF in .gitmodules. @@ -241,7 +271,9 @@ index 7345b56..a36a136 100644         url = https://gitee.com/willcoder/git_submodule.git +       branch = stable ``` -这非常有趣,因为我们可以直接看到将要提交到子模块中的提交日志。 提交之后,你也可以运行`git log -p`查看这个信息。 + +这非常有趣,因为我们可以直接看到将要提交到子模块中的提交日志。提交之后,你也可以运行 `git log -p` 查看这个信息。 + ```shell $ git log -p --submodule commit 873826777c305398b44496d0fb2c3408fece5f50 (HEAD -> master, origin/master, origin/HEAD) @@ -259,14 +291,16 @@ index 0000000..7345b56 +       url = https://gitee.com/willcoder/git_submodule.git Submodule git_submodule 0000000...0c7ce50 (new submodule) ``` -当运行`git submodule update --remote`时,Git 默认会尝试更新**所有**子模块, 所以如果有很多子模块的话,你可以传递想要更新的子模块的名字。 + +当运行 `git submodule update --remote` 时,Git 默认会尝试更新**所有**子模块, 所以如果有很多子模块的话,你可以传递想要更新的子模块的名字。 + **从项目远端拉取上游更改** -默认情况下,`git pull`命令会递归地抓取子模块的更改。 然而,它不会**更新**子模块。所以需要运行`git submodule update --init --recursive`。 +默认情况下,`git pull` 命令会递归地抓取子模块的更改。 然而,它不会**更新**子模块。所以需要运行 `git submodule update --init --recursive`。 -如果你想自动化此过程,那么可以为`git pull`命令添加`--recurse-submodules`选项(从 Git 2.14 开始)。 这会让 Git 在拉取后运行`git submodule update`,将子模块置为正确的状态。 此外,如果你想让 Git 总是以`--recurse-submodules`拉取,可以将配置选项`submodule.recurse`设置为`true`(从 Git 2.15 开始可用于`git pull`)。此选项会让 Git 为所有支持`--recurse-submodules`的命令使用该选项(除`clone`以外)。 +如果你想自动化此过程,那么可以为 `git pull` 命令添加 `--recurse-submodules` 选项(从 Git 2.14 开始)。这会让 Git 在拉取后运行 `git submodule update`,将子模块置为正确的状态。 此外,如果你想让 Git 总是以 `--recurse-submodules` 拉取,可以将配置选项 `submodule.recurse` 设置为 `true`(从 Git 2.15 开始可用于 `git pull`)。此选项会让 Git 为所有支持 `--recurse-submodules` 的命令使用该选项(除 `clone` 以外)。 -在为父级项目拉取更新时,还会出现一种特殊的情况:在你拉取的提交中, 可能`.gitmodules`文件中记录的子模块的 URL 发生了改变。 比如,若子模块项目改变了它的托管平台,就会发生这种情况。 此时,若父级项目引用的子模块提交不在仓库中本地配置的子模块远端上,那么执行`git pull --recurse-submodules`或`git submodule update`就会失败。 为了补救,`git submodule sync`命令需要: +在为父级项目拉取更新时,还会出现一种特殊的情况:在你拉取的提交中,可能 `.gitmodules` 文件中记录的子模块的 URL 发生了改变。比如,若子模块项目改变了它的托管平台,就会发生这种情况。此时,若父级项目引用的子模块提交不在仓库中本地配置的子模块远端上,那么执行 `git pull --recurse-submodules` 或 `git submodule update` 就会失败。为了补救,`git submodule sync` 命令需要: ```shell # 将新的 URL 复制到本地配置中 @@ -274,10 +308,12 @@ $ git submodule sync --recursive # 从新 URL 更新子模块 $ git submodule update --init --recursive ``` + ### **在子模块上工作** + 现在我们将通过一个例子来演示如何在子模块与主项目中同时做修改,以及如何同时提交与发布那些修改。 -为了将子模块设置得更容易进入并修改,你需要做两件事。 首先,进入每个子模块并检出其相应的工作分支。 接着,若你做了更改就需要告诉 Git 它该做什么,然后运行`git submodule update --remote`来从上游拉取新工作。 你可以选择将它们合并到你的本地工作中,也可以尝试将你的工作变基到新的更改上。 +为了将子模块设置得更容易进入并修改,你需要做两件事。首先,进入每个子模块并检出其相应的工作分支。接着,若你做了更改就需要告诉 Git 它该做什么,然后运行 `git submodule update --remote` 来从上游拉取新工作。你可以选择将它们合并到你的本地工作中,也可以尝试将你的工作变基到新的更改上。 首先,让我们进入子模块目录然后检出一个分支。 @@ -286,7 +322,9 @@ $ cd git_submodule/ $ git checkout -b stable Switched to a new branch 'stable' ``` -然后尝试用 “merge” 选项来更新子模块。 为了手动指定它,我们只需给`update`添加`--merge`选项即可。 这时我们将会看到服务器上的这个子模块有一个改动并且它被合并了进来。 + +然后尝试用 “merge” 选项来更新子模块。为了手动指定它,我们只需给 `update` 添加 `--merge` 选项即可。这时我们将会看到服务器上的这个子模块有一个改动并且它被合并了进来。 + ```shell $ cd .. $ git submodule update --remote --merge @@ -304,7 +342,9 @@ Fast-forward  1 file changed, 3 insertions(+), 1 deletion(-) Submodule path 'git_submodule': merged in 'a7597dad4a94bec59bd44d36e53939add9735ada' ``` -如果我们进入子模块目录,可以发现新的改动已经合并入本地`stable`分支。 现在让我们看看当我们对库做一些本地的改动而同时其他人推送另外一个修改到上游时会发生什么。 + +如果我们进入子模块目录,可以发现新的改动已经合并入本地 `stable` 分支。现在让我们看看当我们对库做一些本地的改动而同时其他人推送另外一个修改到上游时会发生什么。 + ```shell $ cd git_submodule/ $ vi my_submodule.txt @@ -312,19 +352,25 @@ $ git commit -am 'my push test' [stable 926118a] my push test  1 file changed, 5 insertions(+), 1 deletion(-) ``` + 如果我们现在更新子模块,就会看到当我们在本地做了更改时上游也有一个改动,我们需要将它并入本地。 + ```shell $ cd .. $ git submodule update --remote --rebase Current branch stable is up to date. Submodule path 'git_submodule': rebased into 'a7597dad4a94bec59bd44d36e53939add9735ada' ``` -如果你忘记`--rebase`或`--merge`,Git 会将子模块更新为服务器上的状态。并且会将项目重置为一个游离的 HEAD 状态。 + +如果你忘记 `--rebase` 或 `--merge`,Git 会将子模块更新为服务器上的状态。并且会将项目重置为一个游离的 HEAD 状态。 + ```shell $ git submodule update --remote Submodule path 'git_submodule': checked out 'a7597dad4a94bec59bd44d36e53939add9735ada' ``` -即便这真的发生了也不要紧,你只需回到目录中再次检出你的分支(即还包含着你的工作的分支)然后手动地合并或变基`origin/stable`(或任何一个你想要的远程分支)就行了。 + +即便这真的发生了也不要紧,你只需回到目录中再次检出你的分支(即还包含着你的工作的分支)然后手动地合并或变基 `origin/stable`(或任何一个你想要的远程分支)就行了。 + 如果你没有提交子模块的改动,那么运行一个子模块更新也不会出现问题,此时 Git 会只抓取更改而并不会覆盖子模块目录中未保存的工作。 如果你做了一些与上游改动冲突的改动,当运行更新时 Git 会让你知道。 @@ -337,7 +383,9 @@ Recorded preimage for 'my_submodule.txt' Automatic merge failed; fix conflicts and then commit the result. Unable to merge 'dd63fb4c96cc5fcd1af3595a995cb5e0b9ab6495' in submodule path 'git_submodule' ``` + 你可以进入子模块目录中然后就像平时那样修复冲突。 + ### **发布子模块改动** 现在我们的子模块目录中有一些改动。 其中有一些是我们通过更新从上游引入的,而另一些是本地生成的,由于我们还没有推送它们,所以对任何其他人都不可用。 @@ -359,8 +407,10 @@ Submodule git_submodule 0c7ce50..0b924ac:   > update my_submodule.txt.   > update my_submodule.txt. ``` + 如果我们只推送主项目而不推送子模块,检出我们项目的人可能会出现错误,为了确保这不会发生,可以让 Git 在推送到主项目前检查所有子模块是否已推送。 -`git push`命令接受可以设置为 “check” 或 “on-demand” 的`--recurse-submodules`参数。 如果任何提交的子模块改动没有推送那么 “check” 选项会直接使`push`操作失败。 + +`git push` 命令接受可以设置为 “check” 或 “on-demand” 的 `--recurse-submodules` 参数。 如果任何提交的子模块改动没有推送那么 “check” 选项会直接使 `push` 操作失败。 ```shell $ git push --recurse-submodules=check @@ -373,13 +423,16 @@ or cd to the path and use git push to push them to a remote. ``` -它给我们了一些建议,指导接下来该如何做。 最简单的选项是进入每一个子模块中然后手动推送到远程仓库,确保它们能被外部访问到,之后再次尝试这次推送。 如果你想要对所有推送都执行检查,那么可以通过设置`git config push.recurseSubmodules check`让它成为默认行为。 + +它给我们了一些建议,指导接下来该如何做。最简单的选项是进入每一个子模块中然后手动推送到远程仓库,确保它们能被外部访问到,之后再次尝试这次推送。如果你想要对所有推送都执行检查,那么可以通过设置 `git config push.recurseSubmodules check` 让它成为默认行为。 + 另一个选项是使用 “on-demand” 值,它会尝试为你这样做。 ```shell $ git push --recurse-submodules=on-demand ``` -Git 进入到子模块中然后在推送主项目前推送了它。 如果那个子模块因为某些原因推送失败,主项目也会推送失败。 你也可以通过设置`git config push.recurseSubmodules on-demand`让它成为默认行为。 + +Git 进入到子模块中然后在推送主项目前推送了它。 如果那个子模块因为某些原因推送失败,主项目也会推送失败。你也可以通过设置 `git config push.recurseSubmodules on-demand` 让它成为默认行为。 ### **合并子模块改动** @@ -394,8 +447,10 @@ CONFLICT (content): Merge conflict in my_submodule.txt Recorded preimage for 'my_submodule.txt' Automatic merge failed; fix conflicts and then commit the result. ``` + 所以本质上 Git 在这里指出了子模块历史中的两个分支记录点已经分叉并且需要合并。 它将其解释为 “merge following commits not found” (未找到接下来需要合并的提交),虽然这有点令人困惑,不过之后我们会解释为什么是这样。 -为了解决这个问题,你需要弄清楚子模块应该处于哪种状态。 奇怪的是,Git 并不会给你多少能帮你摆脱困境的信息,甚至连两边提交历史中的 SHA-1 值都没有。 幸运的是,这很容易解决。 如果你运行`git diff`,就会得到试图合并的两个分支中记录的提交的 SHA-1 值。 + +为了解决这个问题,你需要弄清楚子模块应该处于哪种状态。奇怪的是,Git 并不会给你多少能帮你摆脱困境的信息,甚至连两边提交历史中的 SHA-1 值都没有。幸运的是,这很容易解决。 如果你运行 `git diff`,就会得到试图合并的两个分支中记录的提交的 SHA-1 值。 1. 首先解决冲突 2. 然后返回到主项目目录中 @@ -420,7 +475,9 @@ Auto-merging git_submodule CONFLICT (submodule): Merge conflict in git_submodule Automatic merge failed; fix conflicts and then commit the result. ``` -Git 建议的命令是更新索引,就像你运行了`git add`那样,这样会清除冲突然后提交。 不过你可能不应该这样做。你可以轻松地进入子模块目录,查看差异是什么,快进到这次提交,恰当地测试,然后提交它。 + +Git 建议的命令是更新索引,就像你运行了 `git add` 那样,这样会清除冲突然后提交。不过你可能不应该这样做。你可以轻松地进入子模块目录,查看差异是什么,快进到这次提交,恰当地测试,然后提交它。 + ```shell $ cd git_submodule/ $ git merge 9fd905e @@ -430,18 +487,21 @@ $ cd .. $ git add git_submodule $ git commit -am 'Fast forwarded to a common submodule child' ``` + 这些命令完成了同一件事,但是通过这种方式你至少可以验证工作是否有效,以及当你在完成时可以确保子模块目录中有你的代码。 + ## **其他** ### **子模块遍历** -有一个`foreach`子模块命令,它能在每一个子模块中运行任意命令。 如果项目中包含了大量子模块,这会非常有用。 +有一个 `foreach` 子模块命令,它能在每一个子模块中运行任意命令。如果项目中包含了大量子模块,这会非常有用。 ```shell $ git submodule foreach 'git stash' Entering 'git_submodule' Saved working directory and index state WIP on (no branch): 0b924ac conflict ok ``` + ### **有用的别名** 你可能想为其中一些命令设置别名,因为它们可能会非常长而你又不能设置选项作为它们的默认选项。 @@ -451,4 +511,5 @@ $ git config alias.sdiff '!'"git diff && git submodule foreach 'git diff'" $ git config alias.spush 'push --recurse-submodules=on-demand' $ git config alias.supdate 'submodule update --remote --merge' ``` -这样当你想要更新子模块时可以简单地运行`git supdate`,或`git spush`检查子模块依赖后推送。 \ No newline at end of file + +这样当你想要更新子模块时可以简单地运行 `git supdate`,或 `git spush` 检查子模块依赖后推送。 diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/11. \346\211\223\345\214\205.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/11. \346\211\223\345\214\205.md" index 838a43f49b3aaba463cd2f2cd78d26f660eecefd..f84b147d8083304a083ea8381a264b11e5611b26 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/11. \346\211\223\345\214\205.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/11. \346\211\223\345\214\205.md" @@ -3,17 +3,17 @@ title: 打包 permalink: /git-tutorial/git-bundle --- -`git bundle` + 虽然我们已经了解了网络传输 Git 数据的常用方法(如 HTTP,SSH 等),但还有另外一种不太常见却又十分有用的方式。 -Git 可以将它的数据“打包”到一个文件中。 这在许多场景中都很有用。 有可能你的网络中断了,但你又希望将你的提交传给你的合作者。 可能你不在办公网中并且出于安全考虑没有给你接入内网的权限。 可能你的无线、有线网卡坏掉了。 可能你现在没有共享服务器的权限,你又希望通过邮件将更新发送给别人, 却不希望通过`format-patch`的方式传输 40 个提交。 +Git 可以将它的数据“打包”到一个文件中。 这在许多场景中都很有用。有可能你的网络中断了,但你又希望将你的提交传给你的合作者。 可能你不在办公网中并且出于安全考虑没有给你接入内网的权限。可能你的无线、有线网卡坏掉了。可能你现在没有共享服务器的权限,你又希望通过邮件将更新发送给别人,却不希望通过 `format-patch` 的方式传输 40 个提交。 -这些情况下`git bundle`就会很有用。`bundle`命令会将`git push`命令所传输的所有内容打包成一个二进制文件, 你可以将这个文件通过邮件或者闪存传给其他人,然后解包到其他的仓库中。 +这些情况下 `git bundle` 就会很有用。`bundle` 命令会将 `git push` 命令所传输的所有内容打包成一个二进制文件, 你可以将这个文件通过邮件或者闪存传给其他人,然后解包到其他的仓库中。 来看看一个简单的例子。 假设你有一个包含两个提交的仓库: -如果你想把这个仓库发送给其他人但你没有其他仓库的权限,或者就是懒得新建一个仓库, 你就可以用`git bundle create`命令来打包。 +如果你想把这个仓库发送给其他人但你没有其他仓库的权限,或者就是懒得新建一个仓库,你就可以用 `git bundle create` 命令来打包。 ```shell $ git bundle create git_submodle.bundle HEAD master @@ -24,10 +24,12 @@ Compressing objects: 100% (5/5), done. Writing objects: 100% (12/12), 1.03 KiB | 529.00 KiB/s, done. Total 12 (delta 0), reused 0 (delta 0) ``` -然后你就会有一个bundle文件,该文件包含了所有重建该仓库`master`分支所需的数据。 在使用`bundle`命令时,你需要列出所有你希望打包的引用或者提交的区间。 如果你希望这个仓库可以在别处被克隆,你应该像例子中那样增加一个 HEAD 引用。 -你可以将这个`git_submodle.bundle`文件通过邮件或者U盘传给别人。 -另一方面,假设别人传给你一个`git_submodle.bundle`文件并希望你在这个项目上工作。 你可以从这个二进制文件中克隆出一个目录,就像从一个 URL 克隆一样。 +然后你就会有一个 bundle 文件,该文件包含了所有重建该仓库 `master` 分支所需的数据。在使用 `bundle` 命令时,你需要列出所有你希望打包的引用或者提交的区间。 如果你希望这个仓库可以在别处被克隆,你应该像例子中那样增加一个 HEAD 引用。 + +你可以将这个 `git_submodle.bundle` 文件通过邮件或者U盘传给别人。 + +另一方面,假设别人传给你一个 `git_submodle.bundle` 文件并希望你在这个项目上工作。你可以从这个二进制文件中克隆出一个目录,就像从一个 URL 克隆一样。 ```shell $ git clone git_submodle.bundle @@ -40,16 +42,20 @@ a7597da update my_submodule.txt. a5cbd40 update my_submodule.txt. 0c7ce50 init submodule ``` -如果你在打包时没有包含 HEAD 引用,你还需要在命令后指定一个`-b master`或者其他被引入的分支, 否则 Git 不知道应该检出哪一个分支。 + +如果你在打包时没有包含 HEAD 引用,你还需要在命令后指定一个 `-b master` 或者其他被引入的分支,否则 Git 不知道应该检出哪一个分支。 + 现在假设你提交了修订,并且要用邮件或者U盘将新的提交放在一个包里传回去。我们可以像上面那样将整个仓库打包,但最好仅仅打包变更的部分。 -我们可以用`git bundle create`命令,加上我们想用的文件名,以及要打包的提交区间。 +我们可以用 `git bundle create` 命令,加上我们想用的文件名,以及要打包的提交区间。 ```shell $ git bundle create commits.bundle master ^9a466c5 ``` -现在在我们的目录下会有一个`commits.bundle`文件。 如果我们把这个文件发送给我们的合作者,她可以将这个文件导入到原始的仓库中, 即使在这期间已经有其他的工作提交到这个仓库中。 -当她拿到这个包时,她可以在导入到仓库之前查看这个包里包含了什么内容。`bundle verify`命令可以检查这个文件是否是一个合法的 Git 包,是否拥有共同的祖先来导入。 + +现在在我们的目录下会有一个 `commits.bundle` 文件。如果我们把这个文件发送给我们的合作者,她可以将这个文件导入到原始的仓库中,即使在这期间已经有其他的工作提交到这个仓库中。 + +当她拿到这个包时,她可以在导入到仓库之前查看这个包里包含了什么内容。`bundle verify` 命令可以检查这个文件是否是一个合法的 Git 包,是否拥有共同的祖先来导入。 ```shell $ git bundle verify ../commits.bundle @@ -59,24 +65,32 @@ The bundle requires these 1 ref 9a466c572fe88b195efd356c3f2bbeccdb504102 second commit ../commits.bundle is okay ``` -如果打包工具仅仅把最后两个提交打包,而不是三个,原始的仓库是无法导入这个包的, 因为这个包缺失了必要的提交记录。这时候`verify`的输出类似: + +如果打包工具仅仅把最后两个提交打包,而不是三个,原始的仓库是无法导入这个包的,因为这个包缺失了必要的提交记录。这时候 `verify` 的输出类似: + ```shell $ git bundle verify ../commits-bad.bundle error: Repository lacks these prerequisite commits: error: 7011d3d8fc200abe0ad561c011c3852a4b7bbe95 third commit - second repo ``` -而我们的第一个包是合法的,所以我们可以从这个包里提取出提交。 如果你想查看这边包里可以导入哪些分支,同样有一个命令可以列出这些顶端: + +而我们的第一个包是合法的,所以我们可以从这个包里提取出提交。如果你想查看这边包里可以导入哪些分支,同样有一个命令可以列出这些顶端: + ```shell $ git bundle list-heads ../commits.bundle 71b84daaf49abed142a373b6e5c59a22dc6560dc refs/heads/master ``` -`verify`子命令同样可以告诉你有哪些顶端。 该功能的目的是查看哪些是可以被拉入的,所以你可以使用`fetch`或者`pull`命令从包中导入提交。 这里我们要从包中取出`master`分支到我们仓库中的**other-master**分支: + +`verify` 子命令同样可以告诉你有哪些顶端。该功能的目的是查看哪些是可以被拉入的,所以你可以使用 `fetch` 或者 `pull` 命令从包中导入提交。这里我们要从包中取出 `master` 分支到我们仓库中的 **other-master** 分支: + ```shell $ git fetch ../commits.bundle master:other-master From ../commits.bundle * [new branch] master -> other-master ``` -可以看到我们已经将提交导入到`other-master`分支,以及在这期间我们自己在`master`分支上的提交。 + +可以看到我们已经将提交导入到 `other-master` 分支,以及在这期间我们自己在 `master` 分支上的提交。 + ```shell $ git log --oneline --decorate --graph --all * 8255d41 (HEAD, master) third commit - first repo @@ -87,4 +101,6 @@ $ git log --oneline --decorate --graph --all * 9a466c5 second commit * b1ec324 first commit ``` -因此,当你在没有合适的网络或者可共享仓库的情况下,`git bundle`很适合用于共享或者网络类型的操作。 \ No newline at end of file + +因此,当你在没有合适的网络或者可共享仓库的情况下,`git bundle` 很适合用于共享或者网络类型的操作。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/12. \346\233\277\346\215\242.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/12. \346\233\277\346\215\242.md" index 6fe8a5f5879656a20a5e753916b39f462ae107dd..ec07d9876477db7f1e94204200b7006846658643 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/12. \346\233\277\346\215\242.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/12. \346\233\277\346\215\242.md" @@ -3,13 +3,13 @@ title: 替换 permalink: /git-tutorial/git-replace --- -`git replace` + 我们之前强调过,Git 对象数据库中的对象是不可改变的, 然而 Git 提供了一种有趣的方式来用其他对象**假装**替换数据库中的 Git 对象。 -`replace`命令可以让你在 Git 中指定**某个对象**并告诉 Git:“每次遇到这个 Git 对象时,假装它是**其它对象**”。 在你用一个不同的提交替换历史中的一个提交而不想以`git filter-branch`之类的方式重建完整的历史时,这会非常有用。 +`replace`命令可以让你在 Git 中指定**某个对象**并告诉 Git:“每次遇到这个 Git 对象时,假装它是**其它对象**”。在你用一个不同的提交替换历史中的一个提交而不想以 `git filter-branch` 之类的方式重建完整的历史时,这会非常有用。 -让我们来试试吧。 首先获取一个已经存在的仓库,并将其分成两个仓库,一个是最近的仓库,一个是历史版本的仓库, 然后我们将看到如何在不更改仓库 SHA-1 值的情况下通过`replace`命令来合并他们。 +让我们来试试吧。首先获取一个已经存在的仓库,并将其分成两个仓库,一个是最近的仓库,一个是历史版本的仓库, 然后我们将看到如何在不更改仓库 SHA-1 值的情况下通过 `replace` 命令来合并他们。 ```shell $ git log --oneline @@ -18,7 +18,9 @@ a7597da update my_submodule.txt. a5cbd40 update my_submodule.txt. 0c7ce50 init submodule ``` -创建历史版本的历史很容易,我们可以只将一个历史中的分支推送到一个新的远程仓库的`master`分支。 + +创建历史版本的历史很容易,我们可以只将一个历史中的分支推送到一个新的远程仓库的 `master` 分支。 + ```shell $ git branch history a5cbd40  $ git log --oneline --decorate @@ -27,7 +29,8 @@ a7597da (history) update my_submodule.txt. a5cbd40 update my_submodule.txt. 0c7ce50 init submodule ``` -现在我们可以把这个新的`history`分支推送到我们新仓库的`master`分支: + +现在我们可以把这个新的 `history` 分支推送到我们新仓库的 `master` 分支: ```shell $ git remote add p-h https://gitee.com/willcoder/p-h.git @@ -42,16 +45,19 @@ remote: Powered by GITEE.COM [GNK-5.0] To https://gitee.com/willcoder/p-h.git  * [new branch]      history -> master ``` -这样一来,我们的历史版本就发布了。 稍难的部分则是删减我们最近的历史来让它变得更小。 我们需要一个重叠以便于用一个相等的提交来替换另一个提交,这样一来,我们将截断最后的提交。 -在这种情况下,创建一个能够指导扩展历史的基础提交是很有用的。 这样一来,如果其他的开发者想要修改第一次提交或者其他操作时就知道要做些什么,因此,接下来我们要做的是用命令创建一个最初的提交对象,然后将最后的提交变基到它的上面。 -为了这么做,我们需要选择一个点去拆分,对于我们而言是第三个提交(SHA 是`a5cbd40`)。 因此我们的提交将基于此提交树。我们可以使用`commit-tree`命令来创建基础提交, 这样我们就有了一个树,并返回一个全新的、无父节点的 SHA-1 提交对象。 +这样一来,我们的历史版本就发布了。稍难的部分则是删减我们最近的历史来让它变得更小。我们需要一个重叠以便于用一个相等的提交来替换另一个提交,这样一来,我们将截断最后的提交。 + +在这种情况下,创建一个能够指导扩展历史的基础提交是很有用的。这样一来,如果其他的开发者想要修改第一次提交或者其他操作时就知道要做些什么,因此,接下来我们要做的是用命令创建一个最初的提交对象,然后将最后的提交变基到它的上面。 + +为了这么做,我们需要选择一个点去拆分,对于我们而言是第三个提交(SHA 是`a5cbd40`)。因此我们的提交将基于此提交树。我们可以使用 `commit-tree` 命令来创建基础提交,这样我们就有了一个树,并返回一个全新的、无父节点的 SHA-1 提交对象。 ```shell -$  echo 'get history from blah blah blah' | git commit-tree a5cbd40^{tree} +$ echo 'get history from blah blah blah' | git commit-tree a5cbd40^{tree} b06ec96de666b38d61470a566634707b3033a87a ``` -现在我们已经有一个基础提交了,我们可以通过`git rebase --onto`命令来将剩余的历史变基到基础提交之上。`--onto`参数是刚才`commit-tree`命令返回的 SHA-1 值,变基点会成为第二个提交(我们想留下的第一个提交的父提交,`a5cbd40`): + +现在我们已经有一个基础提交了,我们可以通过 `git rebase --onto` 命令来将剩余的历史变基到基础提交之上。`--onto` 参数是刚才 `commit-tree` 命令返回的 SHA-1 值,变基点会成为第二个提交(我们想留下的第一个提交的父提交,`a5cbd40`): ```shell $ git rebase --onto b06ec9 a5cbd40 @@ -59,9 +65,10 @@ First, rewinding head to replay your work on top of it... Applying: update my_submodule.txt. Applying: update my_submodule.txt. ``` -我们已经用基础提交重写了最近的历史,基础提交包括如何重新组成整个历史的说明。 我们可以将新历史推送到新项目中,当其他人克隆这个仓库时,他们仅能看到最近两次提交以及一个包含上述说明的基础提交。 -现在我们将以想获得整个历史的人的身份来初次克隆这个项目。 在克隆这个截断后的仓库后为了得到历史数据,需要添加第二个远程的历史版本库并对其做获取操作: +我们已经用基础提交重写了最近的历史,基础提交包括如何重新组成整个历史的说明。我们可以将新历史推送到新项目中,当其他人克隆这个仓库时,他们仅能看到最近两次提交以及一个包含上述说明的基础提交。 + +现在我们将以想获得整个历史的人的身份来初次克隆这个项目。在克隆这个截断后的仓库后为了得到历史数据,需要添加第二个远程的历史版本库并对其做获取操作: ```shell $ git clone https://gitee.com/willcoder/git_submodule.git @@ -77,7 +84,9 @@ $ git fetch p-h From https://gitee.com/willcoder/p-h  * [new branch]      master     -> p-h/master ``` -现在,协作者在`master`分支中拥有他们最近的提交并且在`p-h/master`分支中拥有过去的提交。 + +现在,协作者在 `master` 分支中拥有他们最近的提交并且在 `p-h/master` 分支中拥有过去的提交。 + ```shell $ git log --oneline master eea6ff3 (master) update my_submodule.txt. @@ -88,15 +97,20 @@ a7597da (p-h/master) update my_submodule.txt. a5cbd40 update my_submodule.txt. 0c7ce50 init submodule ``` -为了合并它们,你可以使用`git replace`命令加上你想替换的提交信息来进行替换。 这样一来,我们就可以将`master`分支中的第四个提交替换为`p-/master`分支中的“第四个”提交。 + +为了合并它们,你可以使用 `git replace` 命令加上你想替换的提交信息来进行替换。这样一来,我们就可以将 `master` 分支中的第四个提交替换为 `p-/master` 分支中的“第四个”提交。 + ```shell $ git replace 0f808ad a7597da ``` -现在,查看`master`分支中的历史信息,显示如下: + +现在,查看 `master` 分支中的历史信息,显示如下: + ```shell $ git log --oneline master eea6ff3 (master) update my_submodule.txt. 0f808ad (replaced) update my_submodule.txt. a5cbd40 update my_submodule.txt. 0c7ce50 init submodule -``` \ No newline at end of file +``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/13. \345\207\255\350\257\201\345\255\230\345\202\250.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/13. \345\207\255\350\257\201\345\255\230\345\202\250.md" index 33f3c093a3ae541a0c8b8597b6b1d10c7d8b2939..106823f08cba3e6d5206f0f53e017d612d626cca 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/13. \345\207\255\350\257\201\345\255\230\345\202\250.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/13. \345\207\255\350\257\201\345\255\230\345\202\250.md" @@ -3,14 +3,14 @@ title: 凭证存储 permalink: /git-tutorial/git-credential --- -`git credential` + ## 凭证存储设置 如果你使用的是 SSH 方式连接远端,并且设置了一个没有口令的密钥,这样就可以在不输入用户名和密码的情况下安全地传输数据。 然而,这对 HTTP 协议来说是不可能的 —— 每一个连接都是需要用户名和密码的,但我们使用时,并没有每次都被要求输入凭证,原因就是Git拥有凭证系统来处理这个事情。 * 默认所有都不缓存。 每一次连接都会询问你的用户名和密码。 -* “cache” 模式会将凭证存放在内存中一段时间。 密码永远不会被存储在磁盘中,并且在15分钟后从内存中清除。 +* “cache” 模式会将凭证存放在内存中一段时间。 密码永远不会被存储在磁盘中,并且在 15 分钟后从内存中清除。 * “store” 模式会将凭证用明文的形式存放在磁盘中,并且永不过期。 这意味着除非你修改了你在 Git 服务器上的密码,否则你永远不需要再次输入你的凭证信息。 这种方式的缺点是你的密码是用明文的方式存放在你的 home 目录下。 * 如果你使用的是 Mac,Git 还有一种 “osxkeychain” 模式,它会将凭证缓存到你系统用户的钥匙串中。 这种方式将凭证存放在磁盘中,并且永不过期,但是是被加密的,这种加密方式与存放 HTTPS 凭证以及 Safari 的自动填写是相同的。 * 如果你使用的是 Windows,你可以安装一个叫做 “Git Credential Manager for Windows” 的辅助工具。 这和上面说的 “osxkeychain” 十分类似,但是是使用 Windows Credential Store 来控制敏感信息。 可以在[https://github.com/Microsoft/Git-Credential-Manager-for-Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows)下载。 @@ -19,36 +19,43 @@ permalink: /git-tutorial/git-credential ```shell $ git config --global credential.helper cache ``` + 查看凭证缓存配置: + ```shell git config --list | grep credential ``` + Mac,默认会输出: + ```shell include.path=.gitcredential credential.helper=osxkeychain ``` -对应的也就是Mac的“钥匙串”系统。 -Windows安装GitGUI后,默认会输出: + +对应的也就是 Mac 的“钥匙串”系统。 + +Windows 安装 Git GUI 后,默认会输出: ```shell credential.helper=manager ``` -Git 甚至允许你配置多个辅助工具。 当查找特定服务器的凭证时,Git 会按顺序查询,并且在找到第一个回答时停止查询。 当保存凭证时,Git 会将用户名和密码发送给**所有**配置列表中的辅助工具,它们会按自己的方式处理用户名和密码。 如果你在闪存上有一个凭证文件,但又希望在该闪存被拔出的情况下使用内存缓存来保存用户名密码,`.gitconfig`配置文件如下: +Git 甚至允许你配置多个辅助工具。当查找特定服务器的凭证时,Git 会按顺序查询,并且在找到第一个回答时停止查询。 当保存凭证时,Git 会将用户名和密码发送给**所有**配置列表中的辅助工具,它们会按自己的方式处理用户名和密码。如果你在闪存上有一个凭证文件,但又希望在该闪存被拔出的情况下使用内存缓存来保存用户名密码,`.gitconfig`配置文件如下: ```shell [credential]     helper = store --file G:/test2/fake-project/.git-credentials     helper = cache --timeout 30000 ``` + ![图片](./../../../.vuepress/public/images/WTawtBgQ4ru6U5Fc.png) ## 底层实现 -Git 凭证辅助工具系统的命令是`git credential`,这个命令接收一个参数,并通过标准输入获取更多的参数。 +Git 凭证辅助工具系统的命令是 `git credential`,这个命令接收一个参数,并通过标准输入获取更多的参数。 -举一个例子更容易理解。 我们假设已经配置好一个凭证辅助工具,这个辅助工具保存了`mygithost`的凭证信息。 下面是一个使用 “fill” 命令的会话,当 Git 尝试寻找一个服务器的凭证时就会被调用。 +举一个例子更容易理解。 我们假设已经配置好一个凭证辅助工具,这个辅助工具保存了 `mygithost` 的凭证信息。 下面是一个使用 “fill” 命令的会话,当 Git 尝试寻找一个服务器的凭证时就会被调用。 ```shell $ git credential fill (1) @@ -69,6 +76,7 @@ host=unknownhost username=bob password=s3cre7 ``` + 1. 这是开始交互的命令。 2. Git-credential 接下来会等待标准输入。 我们提供我们所知道的信息:协议和主机名。 3. 一个空行代表输入已经完成,凭证系统应该输出它所知道的信息。 @@ -77,4 +85,5 @@ password=s3cre7 简单来说:就是每次需要用户名密码的时候,都会调用 Git-credential 命令,它会先向辅助程序获取用户密码,如果成功,就用这个获得的用户密码去访问远程仓库。如果获取不到,就会让用户输入一次,并尝试保存下来。 -因此我们第一次使用的时候,会被提示输入用户名密码,就是因为git的内部调用了这个命令。 \ No newline at end of file +因此我们第一次使用的时候,会被提示输入用户名密码,就是因为git的内部调用了这个命令。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/2. \344\272\244\344\272\222\345\274\217\346\232\202\345\255\230.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/2. \344\272\244\344\272\222\345\274\217\346\232\202\345\255\230.md" index fbb204a5ff56af3e763888bfd47c449e2ad911bf..3cc5400e07f0bb37e0d65d93c2c7a46f43b065b9 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/2. \344\272\244\344\272\222\345\274\217\346\232\202\345\255\230.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/2. \344\272\244\344\272\222\345\274\217\346\232\202\345\255\230.md" @@ -7,7 +7,7 @@ permalink: /git-tutorial/git-interactive-stash 当希望替换能替换为多个提交而不是替代在一起成为一个提交,几个临时的 Git 命令可以帮助将文件的特定部分组合成提交。 -如果运行 git add 时使用 -i 或者 --interactive 选项,Git 将会进入一个交互终端模式,显示类似下面的东西: +如果运行 `git add` 时使用 `-i` 或者 `--interactive` 选项,Git 将会进入一个交互终端模式,显示类似下面的东西: ```shell $ git add -i @@ -19,12 +19,14 @@ staged unstaged path 5: patch 6: diff 7: quit 8: help! ``` -在这块区域后是“Commands”命令区域。 在这里你可以做一些工作,包括暂存文件、取消暂存文件、暂存文件的一部分、添加未被追踪的文件、显示暂存内容的区别。 + +在这块区域后是“Commands”命令区域。在这里你可以做一些工作,包括暂存文件、取消暂存文件、暂存文件的一部分、添加未被追踪的文件、显示暂存内容的区别。 + ## 暂存与取消暂存条件 -如果在 What now> 将来后键入u 或2(更新),它会问你想要暂存其中文件, +如果在 What now> 将来后键入 u 或 2(更新),它会问你想要暂存其中文件。 -输入要暂存文件前的数字,例如: +输入要暂存文件前的数字,例如: ```shell *** Commands *** @@ -38,8 +40,10 @@ staged unstaged path * 1: +1/-0 +5/-1 新建文本文档.txt Update>> ``` -文件前面的 *,意味着文件将会被暂存 -如果 Update>> 提示符不输入回车,Git 将会暂存之前选择的文件,意思是,按了回车才是将自己的文件暂存,否则将暂存之前的文件 + +文件前面的 `*`,意味着文件将会被暂存。 + +如果 `Update>>` 提示符不输入回车,Git 将会暂存之前选择的文件,意思是,按了回车才是将自己的文件暂存,否则将暂存之前的文件。 ```shell Update>> 1 @@ -48,8 +52,10 @@ staged unstaged path Update>> updated 1 path ``` -新建文本文档.txt 还没被暂存 -如果这时想要取消暂存的文件,使用。r或3(撤消)选项: + +新建文本文档.txt 还没被暂存。 + +如果这时想要取消暂存的文件,使用。`r` 或 `3`(撤消)选项: ```shell *** Commands *** @@ -65,7 +71,9 @@ staged unstaged path 2: +7/-0 nothing 新建文本文档.txt Revert>> ``` -如果要查看已暂存内容的区别,可以使用 d 或6(区别)命令。它会显示暂存文件的一个列表,可以从中选择想要查看的暂存区别。这跟你在命令行指定 git diff --cached 非常相似: + +如果要查看已暂存内容的区别,可以使用 `d` 或 `6`(区别)命令。它会显示暂存文件的一个列表,可以从中选择想要查看的暂存区别。这跟你在命令行指定 `git diff --cached` 非常相似: + ```shell *** Commands *** 1: status 2: update 3: revert 4: add untracked @@ -83,11 +91,12 @@ index 0000000..509f9ed @@ -0,0 +1 @@ +123s12143 ``` + ## 暂存补丁 Git 暂时存文件的特定部分. -输入 p 或5(补丁) Git 中会询问你想要部分暂存哪些文件,然后,对已选择文件的每一个部分,它都会一个个地显示文件区别并询问你是否想要暂存他们: +输入 `p` 或 `5`(补丁)Git 中会询问你想要部分暂存哪些文件。然后,对已选择文件的每一个部分,它都会一个个地显示文件区别并询问你是否想要暂存他们: ```shell \ No newline at end of file @@ -96,7 +105,9 @@ Git 暂时存文件的特定部分. \ No newline at end of file Stage this hunk [y,n,q,a,d,e,?]? y ``` -这时有很多选项。输入?显示所有可以使用的命令列表: + +这时有很多选项。输入 `?` 显示所有可以使用的命令列表: + ```shell Stage this hunk [y,n,q,a,d,e,?]? ? y - stage this hunk @@ -107,4 +118,6 @@ d - do not stage this hunk or any of the later hunks in the file e - manually edit the current hunk ? - print help ``` -如果你想暂存各个区块,通常你会输入 y 或者 n,但是暂存特定文件里的全部区块链或暂时跳过对一个区块块的处理同样也很有用。 \ No newline at end of file + +如果你想暂存各个区块,通常你会输入 `y` 或者 `n`,但是暂存特定文件里的全部区块链或暂时跳过对一个区块块的处理同样也很有用。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/3. \345\202\250\350\227\217\344\270\216\346\270\205\347\220\206.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/3. \345\202\250\350\227\217\344\270\216\346\270\205\347\220\206.md" index d2d86f1f77226cb2be862c839c8917466fedd98a..bb7fd88955f78f981eeab0cd1c7913c2776a4186 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/3. \345\202\250\350\227\217\344\270\216\346\270\205\347\220\206.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/3. \345\202\250\350\227\217\344\270\216\346\270\205\347\220\206.md" @@ -3,17 +3,15 @@ title: 储藏与清理 permalink: /git-tutorial/stash-and-clean --- -贮藏命令:git stash +当想要切换分支做别的事,又不想把当前分支做到一半的代码提交时,可以使用贮藏命令(`git stash`)。 -当想要切换分支做别的事,又不想把当前分支做到一半的代码提交时,可以使用贮藏( stash )。 - -贮藏会跟踪文件的修改与暂存的改动,然后将未完成的修改保存到一个栈上,可以在任何时候重新应用这些改动. +贮藏会跟踪文件的修改与暂存的改动,然后将未完成的修改保存到一个栈上,可以在任何时候重新应用这些改动。 ## 贮藏工作 -实例: +实例: -改动文件后,`git status` +改动文件后,执行 `git status` 查看当前状态: ```shell $ git status @@ -25,12 +23,14 @@ Changes not staged for commit:         modified:   my_Unfinished_Work.txt no changes added to commit (use "git add" and/or "git commit -a") ``` -贮藏当前的工作`git stash`或`git stash push` + +贮藏当前的工作,执行 `git stash` 或 `git stash push` 命令: ```shell $ git stash Saved working directory and index state WIP on master: a66ee73 unfinishedwork ``` + 再次查看当前状态,现在分支是干净的了。此时,你可以切换分支并在其他地方工作;你的修改被存储在栈上。 ```shell @@ -39,14 +39,16 @@ On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean ``` -查看当前贮藏列表:`git stash list` + +查看当前贮藏列表,执行 `git stash list` 命令: ```shell $ git stash list stash@{0}: WIP on master: a66ee73 unfinishedwork stash@{1}: WIP on master: 60434ac Subject line (try to keep under 50 characters) ``` -应用贮藏其中的一个工作:`git stash apply`。如果不指定一个贮藏,Git 认为指定的是最近的贮藏 + +应用贮藏其中的一个工作,执行 `git stash apply` 命令。如果不指定一个贮藏,Git 认为指定的是最近的贮藏。 ```shell $ git stash apply stash@{0} @@ -58,17 +60,19 @@ Changes not staged for commit:         modified:   my_Unfinished_Work.txt no changes added to commit (use "git add" and/or "git commit -a") ``` -移除贮藏:`git stash drop` + +移除贮藏,执行 `git stash drop` 命令: ```shell $ git stash drop stash@{1} Dropped stash@{1} (ae8139183fd57272bf32c1f7eaabda0c2bf99081) ``` + ## 贮藏的创意性使用 -贮藏变种有用且流行的几个选项: +贮藏变种有用且流行的几个选项: -1.`git stash`命令的`--keep-index`选项:告诉 Git 不仅要贮藏所有已暂存的内容,同时还要将它们保留在索引中。 +1、`git stash` 命令的 `--keep-index` 选项:告诉 Git 不仅要贮藏所有已暂存的内容,同时还要将它们保留在索引中。 ```shell $ git status -s @@ -80,7 +84,9 @@ $ git status -s M  my_Unfinished_Work2.txt M  my_Unfinished_Work3.txt ``` -2.`git stash`指定`--inc lude-untracked`或`-u`选项: Git 会贮藏任何未跟踪文件(默认情况下,`git stash`只会贮藏已修改和暂存的已跟踪文件) + +2、`git stash` 指定 `--inc lude-untracked` 或 `-u` 选项:Git 会贮藏任何未跟踪文件(默认情况下,`git stash`只会贮藏已修改和暂存的已跟踪文件)。 + ```shell $ git status -s M  my_Unfinished_Work2.txt @@ -91,7 +97,9 @@ Saved working directory and index state WIP on master: a732e98 add work $ git status -s $ ``` -3.`git stash`指定`--patch`标记: Git 不会贮藏所有修改过的任何东西, 但是会交互式地提示哪些改动想要贮藏、哪些改动需要保存在工作目录中。 + +3、`git stash` 指定 `--patch` 标记:Git 不会贮藏所有修改过的任何东西, 但是会交互式地提示哪些改动想要贮藏、哪些改动需要保存在工作目录中。 + ```shell $ git stash --patch diff --git a/my_Unfinished_Work2.txt b/my_Unfinished_Work2.txt @@ -114,9 +122,10 @@ Stash this hunk [y,n,q,a,d,e,?]? n Saved working directory and index state WIP on master: a732e98 add work ``` + ## 从贮藏创建一个分支 -如果贮藏了一些工作,将它留在那,然后继续在贮藏的分支上工作,在重新应用工作时可能会有问题。 如果应用尝试修改刚刚修改的文件,你会得到一个合并冲突并不得不解决它。 如果想要一个轻松的方式来再次测试贮藏的改动,可以运行`git stash branch `以你指定的分支名创建一个新分支,检出贮藏工作时所在的提交,重新在那应用工作,然后在应用成功后丢弃贮藏: +如果贮藏了一些工作,将它留在那,然后继续在贮藏的分支上工作,在重新应用工作时可能会有问题。 如果应用尝试修改刚刚修改的文件,你会得到一个合并冲突并不得不解决它。 如果想要一个轻松的方式来再次测试贮藏的改动,可以运行 `git stash branch ` 以你指定的分支名创建一个新分支,检出贮藏工作时所在的提交,重新在那应用工作,然后在应用成功后丢弃贮藏: ```shell $ git stash branch testchanges @@ -136,22 +145,26 @@ Changes not staged for commit:         modified:   my_Unfinished_Work2.txt Dropped refs/stash@{0} (69fd89ac16b7bf45163922fbedac81ed6356a842) ``` + 这是在新分支轻松恢复贮藏工作并继续工作的一个很不错的途径。 + ## 清理工作目录 -`git clean`命令可用来移除工作目录中以一些工作或文件。 +`git clean` 命令可用来移除工作目录中以一些工作或文件。 -但它被设计为从工作目录中移除未被跟踪的文件,是无法找回文件内容的,**需谨慎使用**。较安全的选项是运行`git stash --all`来移除每一个东西并存放在栈中. +但它被设计为从工作目录中移除未被跟踪的文件,是无法找回文件内容的,**需谨慎使用**。较安全的选项是运行 `git stash --all` 来移除每一个东西并存放在栈中。 -你可以使用`git clean`命令去除冗余文件或者清理工作目录。 使用`git clean -f -d`命令来移除工作目录中所有未追踪的文件以及空的子目录。`-f`意味着“强制(force)”或“确定要移除”,使用它需要 Git 配置变量`clean.requireForce`没有显式设置为`false`。 +你可以使用 `git clean` 命令去除冗余文件或者清理工作目录。使用 `git clean -f -d` 命令来移除工作目录中所有未追踪的文件以及空的子目录。`-f` 意味着“强制(force)”或“确定要移除”,使用它需要 Git 配置变量 `clean.requireForce` 没有显式设置为 `false`。 -使用`--dry-run`或`-n`选项:**做一次演习**,然后告诉你将要移除什么,即演练一遍即将要做的操作. +使用 `--dry-run` 或 `-n` 选项:**做一次演习**,然后告诉你将要移除什么,即演练一遍即将要做的操作。 ```shell $ git clean -d -n Would remove my_Unfinished_Work4.txt ``` -默认情况下,`git clean`命令只会移除没有忽略的未跟踪文件。 任何与`.gitignore`或其他忽略文件中的模式匹配的文件都不会被移除。 如果你也想要移除那些文件,例如为了做一次完全干净的构建而移除所有由构建生成的`.o`文件, 可以给`clean`命令增加一个`-x`选项。 + +默认情况下,`git clean` 命令只会移除没有忽略的未跟踪文件。任何与 `.gitignore` 或其他忽略文件中的模式匹配的文件都不会被移除。如果你也想要移除那些文件,例如为了做一次完全干净的构建而移除所有由构建生成的 `.o` 文件,可以给 `clean` 命令增加一个 `-x` 选项。 + ```shell $ git status -s  M my_Unfinished_Work2.txt @@ -162,8 +175,10 @@ Would remove my_Unfinished_Work4.txt $ git clean -n -d -x Would remove my_Unfinished_Work4.txt ``` -`git clean`在将`-n`改为`-f`来真正做之前总是先用-n来运行它做双重检验。另一个小心处理过程的方式是使用`-i`或者`interactive`” 标记来运行它。 -交互模式运行 clean 命令: + +`git clean` 在将 `-n` 改为 `-f` 来真正做之前总是先用-n来运行它做双重检验。另一个小心处理过程的方式是使用 `-i` 或者 `interactive` 标记来运行它。 + +交互模式运行 `clean` 命令: ```shell $ git clean -x -i @@ -174,3 +189,4 @@ Would remove the following item:     4: ask each             5: quit                 6: help What now> ``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/4. \347\255\276\347\275\262\345\267\245\344\275\234.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/4. \347\255\276\347\275\262\345\267\245\344\275\234.md" index 0c8bbaf801c74fa6dd6b5bc7a6c1839a082fa549..7a2b892c3a039c687268d54a5117d318d49ec7d5 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/4. \347\255\276\347\275\262\345\267\245\344\275\234.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/4. \347\255\276\347\275\262\345\267\245\344\275\234.md" @@ -13,7 +13,9 @@ Git 虽然是密码级安全,但它也不是万无一失的。 如果你从网 $ gpg --list-keys gpg: /c/Users/Administrator/.gnupg/trustdb.gpg: trustdb created ``` -如果你没安装密钥,可以使用 gpg--gen-key 生成一个. + +如果你没安装密钥,可以使用 `gpg --gen-key` 生成一个。 + ```shell $ gpg --gen-key gpg (GnuPG) 1.4.22; Copyright (C) 2015 Free Software Foundation, Inc. @@ -71,14 +73,18 @@ pub 2048R/AF53EA1B 2020-09-02 uid will.wang (will) sub 2048R/4188B8D3 20 ``` -一旦你有一个可以签署的私钥,可以通过设置 Git 的 user.signingkey 选项来签署。 + +一旦你有一个可以签署的私钥,可以通过设置 Git 的 `user.signingkey` 选项来签署。 + ```shell $ git config --global user.signingkey 0A46826A ``` + 现在 Git 默认使用你的密钥来签署标签与提交。 + ## 签署标签 -若已设置好一个 GPG 私钥,可使用它来签署新的标签.所需要做的只是使用 -s 代替 -a 即可: +若已设置好一个 GPG 私钥,可使用它来签署新的标签.所需要做的只是使用 `-s` 代替 `-a` 即可: ```shell $ git tag -s v1.5 -m 'my signed 1.5 tag' @@ -86,7 +92,9 @@ You need a passphrase to unlock the secret key for user: "will.wang (will) " 2048-bit RSA key, ID AF53EA1B, created 2020-09-02 ``` -如果在那个标签上运行 git show,会看到你的 GPG 签名附属在后面: + +如果在那个标签上运行 `git show`,会看到你的 GPG 签名附属在后面: + ```shell $ git show v1.5 tag v1.5 @@ -113,9 +121,10 @@ diff --git a/my_Unfinished_Work3.txt b/my_Unfinished_Work3.txt new file mode 100644 index 0000000..e69de29 ``` + ## 验证标签 -要验证一个签署的标签,可以运行 `git tag -v `。 这个命令使用 GPG 来验证签名。 为了验证能正常工作,签署者的公钥需要在你的钥匙链中。 +要验证一个签署的标签,可以运行 `git tag -v `。 这个命令使用 GPG 来验证签名。为了验证能正常工作,签署者的公钥需要在你的钥匙链中。 ```shell $ git tag -v v1.5 @@ -128,16 +137,19 @@ tag v1.5 tagger will 1599490736 +0800 my signed 1.5 tag ``` + 如果没有签署者的公钥,那么你将会得到类似下面的东西: + ```shell gpg: Signature made 2020年09月 2日 周三 22:58:57 gpg: using RSA key 9EEE8AE9AF53EA1B gpg: Can't check signature: public key not found error: could not verify the tag 'v1.5' ``` + ## 签署提交 -在最新版本的 Git 中(v1.7.9 及以上),也可以签署个人提交。 如果相对于标签而言你对直接签署到提交更感兴趣的话,所有要做的只是增加一个 -S 到 git commit 命令。 +在最新版本的 Git 中(v1.7.9 及以上),也可以签署个人提交。如果相对于标签而言你对直接签署到提交更感兴趣的话,所有要做的只是增加一个 `-S` 到 `git commit` 命令。 ```shell $ git commit -a -S -m 'signed commit' @@ -147,7 +159,9 @@ user: "will.wang (will) " [master 3b69384] signed commit  2 files changed, 2 insertions(+) ``` -**git log 也有一个 --show-signature 选项来查看及验证这些签名。** + +`git log` 也有一个 `--show-signature` 选项来查看及验证这些签名。 + ```shell $ git log --show-signature -1 commit 3b69384a52720f9efcd282f825824171013ee120 (HEAD -> master) @@ -158,7 +172,9 @@ Author: will Date:   Mon Sep 2 23:06:11 2020 +0800     signed commit ``` -另外,也可以配置 git log 来验证任何找到的签名并将它们以 %G? 格式列在输出中。 + +另外,也可以配置 `git log` 来验证任何找到的签名并将它们以 `%G?` 格式列在输出中。 + ```shell $ git log --pretty="format:%h %G? %aN  %s" 3b69384 G will  signed commit @@ -172,8 +188,10 @@ d3c8035 N will  git merge d76809c N wangzhenwei  update ca671b5 N will  init ``` + 这里我们可以看到只有最后一次提交是签署并有效的,而之前的提交都不是。 -在 Git 1.8.3 及以后的版本中,git merge 与 git pull 可以使用 --verify-signatures 选项来检查并拒绝没有携带可信 GPG 签名的提交。 + +在 Git 1.8.3 及以后的版本中,`git merge` 与 `git pull` 可以使用 `--verify-signatures` 选项来检查并拒绝没有携带可信 GPG 签名的提交。 如果使用这个选项来合并一个包含未签名或有效的提交的分支时,合并不会生效。 @@ -181,7 +199,9 @@ ca671b5 N will  init $ git merge --verify-signatures non-verify fatal: Commit ab06180 does not have a GPG signature. ``` + 如果合并包含的只有有效的签名的提交,合并命令会提示所有的签名它已经检查过了然后会继续向前。 + ```shell $ git merge --verify-signatures signed-branch Commit 13ad65e has a good GPG signature by Scott Chacon (Git signing key) @@ -190,7 +210,9 @@ Fast-forward README | 2 ++ 1 file changed, 2 insertions(+) ``` -也可以给 git merge 命令附加 -S 选项来签署自己生成的合并提交。 下面的例子演示了验证将要合并的分支的每一个提交都是签名的并且签署最后生成的合并提交。 + +也可以给 `git merge` 命令附加 `-S` 选项来签署自己生成的合并提交。下面的例子演示了验证将要合并的分支的每一个提交都是签名的并且签署最后生成的合并提交。 + ```shell $ git merge --verify-signatures -S signed-branch Commit 13ad65e has a good GPG signature by Scott Chacon (Git signing key) @@ -201,3 +223,4 @@ Merge made by the 'recursive' strategy. README | 2 ++ 1 file changed, 2 insertions(+) ``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/5. \346\220\234\347\264\242.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/5. \346\220\234\347\264\242.md" index 7becffb5d93c36954dfe5f718ae467034dcd6d27..bd92f02e6c39ee9f8ee57bdde32934f9916ed6ff 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/5. \346\220\234\347\264\242.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/5. \346\220\234\347\264\242.md" @@ -2,60 +2,69 @@ title: 搜索 permalink: /git-tutorial/git-grep --- -Git 提供了两个工具来快速地从 Git 数据库中浏览代码和提交. + +Git 提供了两个工具来快速地从 Git 数据库中浏览代码和提交。 ## Git Grep -`grep`命令可以使你方便地从提交历史,工作目录,甚至索引中查找一个字符或者正则表达式. +`grep` 命令可以使你方便地从提交历史、工作目录,甚至索引中查找一个字符或者正则表达式。 -默认情况下`git grep`会查找你工作目录的文件。第一种变体是,可以传递`-n`或者`--line-number`选项数来输出 Git 找出的匹配行号。 +默认情况下 `git grep` 会查找你工作目录的文件。第一种变体是可以传递 `-n` 或者 `--line-number` 选项数来输出 Git 找出的匹配行号。 ```shell $ git grep -n miss my_Unfinished_Work2.txt:1:miss you ``` -`git grep`还支持大量其它有趣的选项。 -例如,若不想打印所有匹配的项,你可以使用`-c`或`--count`选项来让`git grep`输出概述的信息, 其中仅包括那些包含匹配字符串的文件,以及每个文件中包含了多少个匹配。 + +`git grep` 还支持大量其它有趣的选项。 + +例如:如果不想打印所有匹配的项,你可以使用 `-c` 或 `--count` 选项来让 `git grep` 输出概述的信息,其中仅包括那些包含匹配字符串的文件,以及每个文件中包含了多少个匹配。 ```shell $ git grep --count you my_Unfinished_Work2.txt:1 my_Unfinished_Work3.txt:1 ``` -搜索字符串的上下文,那么可以传入`-p`或`--show-function`选项来显示每一个匹配的字符串所在的方法或函数: + +搜索字符串的上下文,那么可以传入 `-p` 或 `--show-function` 选项来显示每一个匹配的字符串所在的方法或函数: + ```shell $ git grep -p you my_Unfinished_Work2.txt:miss you my_Unfinished_Work3.txt:hate you ``` -使用`--and`标志来查看复杂的字符串组合,它确保了多个匹配出现在同一文本行中 -比如,我们要查看在旧版本 1.5 的 Git 代码库中定义了常量名包含 “YOU” 或者 “hate” 这两个字符串的行 (这里也用到了`--break`和`--heading`选项来使输出更加容易阅读)。 + +使用 `--and` 标志来查看复杂的字符串组合,它确保了多个匹配出现在同一文本行中。 + +例如:我们要查看在旧版本 1.5 的 Git 代码库中定义了常量名包含 “YOU” 或者 “hate” 这两个字符串的行(这里也用到了 `--break` 和 `--heading` 选项来使输出更加容易阅读)。 ```shell $ git grep --break --heading -n -e '#define' --and \( -e YOU -e hate\) v1.5 ``` -相比于一些常用的搜索命令比如`grep`和`ack`,`git grep`命令有一些的优点。 第一就是速度非常快,第二是你不仅仅可以可以搜索工作目录,还可以搜索任意的 Git 树。 在上一个例子中,我们在一个旧版本的 Git 源代码中查找,而不是当前检出的版本。 -## Git Log Searching -Git 日志搜索 +相比于一些常用的搜索命令比如 `grep` 和 `ack`,`git grep` 命令有一些的优点。第一就是速度非常快,第二是你不仅仅可以可以搜索工作目录,还可以搜索任意的 Git 树。 在上一个例子中,我们在一个旧版本的 Git 源代码中查找,而不是当前检出的版本。 + +## Git 日志搜索 -`git log`命令有许多强大的工具可以通过提交信息甚至是`diff`的内容来找到某个特定的提交。 +`git log` 命令有许多强大的工具,可以通过提交信息甚至是 `diff` 的内容来找到某个特定的提交。 -例如,如果我们想找到 ZLIB_BUF_MAX 常量是什么时候引入的,我们可以使用`-S`选项 (在 Git 中俗称“鹤嘴锄(pickaxe)”选项)来显示新增和删除该字符串的提交。 +例如,如果我们想找到 `ZLIB_BUF_MAX` 常量是什么时候引入的,我们可以使用 `-S` 选项 (在 Git 中俗称“鹤嘴锄(pickaxe)”选项)来显示新增和删除该字符串的提交。 ```shell $ git log -S ZLIB_BUF_MAX --oneline e01503b zlib: allow feeding more than 4GB in one go ef49a7a zlib: zlib can only process 4GB at a time ``` -如果我们查看这些提交的`diff`,我们可以看到在`ef49a7a`这个提交引入了常量,并且在`e01503b`这个提交中被修改了。 -如果你希望得到更精确的结果,你可以使用 -G 选项来使用正则表达式搜索。 -### **Line Log Search (行日志搜索)** +如果我们查看这些提交的 `diff`,我们可以看到在 `ef49a7a` 这个提交引入了常量,并且在 `e01503b` 这个提交中被修改了。 -行日志搜索是另一个相当高级并且有用的日志搜索功能。 在`git log`后加上`-L`选项即可调用,它可以展示代码中一行或者一个函数的历史。 +如果你希望得到更精确的结果,你可以使用 `-G` 选项来使用正则表达式搜索。 -例如,假设我们想查看 zlib.c 文件中`git_deflate_bound`函数的每一次变更, 我们可以执行`git log -L :git_deflate_bound:zlib.c`。 Git 会尝试找出这个函数的范围,然后查找历史记录,并且显示从函数创建之后一系列变更对应的补丁。 +### 行日志搜索 + +行日志搜索(Line Log Search)是另一个相当高级并且有用的日志搜索功能。在 `git log` 后加上 `-L` 选项即可调用,它可以展示代码中一行或者一个函数的历史。 + +例如:假设我们想查看 zlib.c 文件中 `git_deflate_bound` 函数的每一次变更,我们可以执行 `git log -L :git_deflate_bound:zlib.c`。Git 会尝试找出这个函数的范围,然后查找历史记录,并且显示从函数创建之后一系列变更对应的补丁。 ```shell $ git log -L :git_deflate_bound:zlib.c @@ -87,4 +96,12 @@ diff --git a/zlib.c b/zlib.c +} + ``` -如果 Git 无法计算出如何匹配你代码中的函数或者方法,你可以提供一个正则表达式。 例如,这个命令和上面的是等同的:`git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c`。 你也可以提供单行或者一个范围的行号来获得相同的输出。 \ No newline at end of file + +如果 Git 无法计算出如何匹配你代码中的函数或者方法,你可以提供一个正则表达式。例如,下面命令和上面的是等同的: + +```shell +git log -L '/unsigned long git_deflate_bound/',/^}/:zlib.c +``` + +你也可以提供单行或者一个范围的行号来获得相同的输出。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/6. \351\207\215\345\206\231\345\216\206\345\217\262.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/6. \351\207\215\345\206\231\345\216\206\345\217\262.md" index 51ed6ee39f4fa6019686ac945eeb178ef151d271..d506523ef48ea0b35962725b0df8e0dc934c7b19 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/6. \351\207\215\345\206\231\345\216\206\345\217\262.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/6. \351\207\215\345\206\231\345\216\206\345\217\262.md" @@ -5,7 +5,7 @@ permalink: /git-tutorial/git-rebase ## 修改最后一次提交 -修改最后一次提交可能是所有修改历史提交的操作中最常见的一个。一般是:简单修改提交信息,或者通过添加,移除或修改文件来更改提交实际的内容。 +修改最后一次提交可能是所有修改历史提交的操作中最常见的一个需求。一般是简单修改提交信息,或者通过添加、移除或修改文件来更改提交实际的内容。 首先做一次提交: @@ -15,26 +15,31 @@ $ git commit -m 'test commit'  1 file changed, 1 insertion(+)  create mode 100644 my_Unfinished_Work4.txt ``` + 如果,你只是想修改最近一次提交的提交信息,那么很简单: + ```shell $ git commit --amend ``` + ![图片](./../../../.vuepress/public/images/pXxyiOZEqGoGIB3d.png) -上面这条命令会将最后一次的提交信息载入到编辑器中供你修改。 当保存并关闭编辑器后,编辑器会将更新后的提交信息写入新提交中,它会成为新的最后一次提交。 +上面这条命令会将最后一次的提交信息载入到编辑器中供你修改。当保存并关闭编辑器后,编辑器会将更新后的提交信息写入新提交中,它会成为新的最后一次提交。 -另一方面,如果你想要修改最后一次提交的实际内容,那么流程很相似:首先作出你想要补上的修改, 暂存它们,然后用 git commit --amend 以新的改进后的提交来**替换**掉旧有的最后一次提交,使用这个技巧的时候需要小心,因为修正会改变提交的 SHA-1 。 它类似于一个小的变基——如果已经推送了最后一次提交就不要修正它。 +另一方面,如果你想要修改最后一次提交的实际内容,那么流程很相似:首先作出你想要补上的修改,暂存它们,然后用 `git commit --amend` 以新的改进后的提交来**替换**掉旧有的最后一次提交,使用这个技巧的时候需要小心,因为修正会改变提交的 SHA-1。它类似于一个小的变基 —— 如果已经推送了最后一次提交就不要修正它。 ## 修改多个提交说明 -要修改更早的历史提交,Git 没有提供工具,但可以使用 rebase 来衍合一系列的提交到它们原来所在的 HEAD 上而不是移到新的上。你可以通过给 git rebase 增加 -i 选项来以交互方式地运行 rebase。 +要修改更早的历史提交,Git 没有提供工具,但可以使用 `rebase` 来衍合一系列的提交到它们原来所在的 HEAD 上而不是移到新的上。你可以通过给 `git rebase` 增加 `-i` 选项来以交互方式地运行 `rebase`。 -例如,如果想要修改最近三次提交信息,或者那组提交中的任意一个提交信息, 将想要修改的最近一次提交的父提交作为参数传递给 git rebase -i 命令,即 `HEAD~2^` 或 `HEAD~3`。 记住 `~3` 可能比较容易,因为你正尝试修改最后三次提交;但是注意实际上指定了以前的四次提交,即想要修改提交的父提交: +例如,如果想要修改最近三次提交信息,或者那组提交中的任意一个提交信息,将想要修改的最近一次提交的父提交作为参数传递给 `git rebase -i` 命令,即 `HEAD~2^` 或 `HEAD~3`。 记住 `~3` 可能比较容易,因为你正尝试修改最后三次提交;但是注意实际上指定了以前的四次提交,即想要修改提交的父提交。 ```shell $ git rebase -i HEAD~3 ``` -再次记住这是一个变基命令——在 `HEAD~3..HEAD` 范围内的每一个修改了提交信息的提交及其**所有后裔**都会被重写。 不要涉及任何已经推送到中央服务器的提交——这样做会产生一次变更的两个版本,因而使他人困惑。 + +再次记住这是一个变基命令 —— 在 `HEAD~3..HEAD` 范围内的每一个修改了提交信息的提交及其**所有后裔**都会被重写。不要涉及任何已经推送到中央服务器的提交 —— 这样做会产生一次变更的两个版本,因而使他人困惑。 + 运行这个命令会在文本编辑器上给你一个提交的列表,看起来像下面这样: ```shell @@ -62,7 +67,8 @@ pick c7b2f02 test commit ...` to unstage)" 。我们先不要reset,我们运行`git commit`来完成提交。 +此时,由于索引和 HEAD 不同,若运行 `git status` 的话就会看到 “Changes to be committed” 下的该文件变为绿色 ——也就是说,现在预期的下一次提交与上一次提交不同。其实这时候已经有提示可以" (use `git reset HEAD ...` to unstage)" 。我们先不要 reset,我们运行 `git commit` 来完成提交。 ![图片](./../../../.vuepress/public/images/wUK4MWcVx46Uulyt.png) -现在运行`git status`会没有输出,因为三个区域又相同了。 +现在运行 `git status` 会没有输出,因为三个区域又相同了。 ## 重置的作用 -在以下情景中观察`reset`命令会更有意义。 +在以下情景中观察 `reset` 命令会更有意义。 -为了演示这些例子,假设我们修改了项目三次并提交三次。文件的三次版本分别为v1(5a56d3),v2(be6993),v3(9e3b9b)。 +为了演示这些例子,假设我们修改了项目三次并提交三次。文件的三次版本分别为 v1(5a56d3)、v2(be6993)、v3(9e3b9b)。 ```shell commit 9e3b9b667130be604fcd0fb9104361068fb84715 (HEAD -> master) commit be69930a6a7e85c0a3fecff73112e850deace1b9 commit 5a56d30ed040f31c2f711e60f322934df9985753 ``` -当第三次提交完成后,三个区域的版本都是v3。此时想要将版本reset到v2。 + +当第三次提交完成后,三个区域的版本都是 v3。此时想要将版本 reset 到 v2。 ### 第 1 步:移动 HEAD -`reset`做的第一件事是移动 HEAD 的指向。这意味着如果 HEAD 设置为`master`分支(例如,你正在`master`分支上), 运行`git reset be6993`将会使`master`指向 v2。 +`reset` 做的第一件事是移动 HEAD 的指向。这意味着如果 HEAD 设置为 `master` 分支(例如,你正在 `master` 分支上), 运行 `git reset be6993` 将会使 `master` 指向 v2。 -无论你调用了何种形式的带有一个提交的`reset`,它首先都会尝试这样做。 使用`reset --soft`,它将仅仅停在那儿。 +无论你调用了何种形式的带有一个提交的 `reset`,它首先都会尝试这样做。使用 `reset --soft`,它将仅仅停在那儿。 -它指向 v2 本质上是撤销了第三次的`git commit`命令。 当你在运行`git commit`时,Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交。 当你将它`reset`回`HEAD~`(HEAD 的父结点)时,其实就是把该分支移动回原来的位置,而不会改变索引和工作目录。 现在你可以更新索引并再次运行`git commit`来完成`git commit --amend`所要做的事情了。 +它指向 v2 本质上是撤销了第三次的 `git commit` 命令。当你在运行 `git commit` 时,Git 会创建一个新的提交,并移动 HEAD 所指向的分支来使其指向该提交。当你将它 `reset` 回 `HEAD~`(HEAD 的父结点)时,其实就是把该分支移动回原来的位置,而不会改变索引和工作目录。现在你可以更新索引并再次运行 `git commit` 来完成 `git commit --amend` 所要做的事情了。 ### 第 2 步:更新索引(--mixed) -注意,如果你现在运行`git status`的话,就会看到新的 HEAD 和以绿色标出的它和索引之间的区别。 +注意,如果你现在运行 `git status` 的话,就会看到新的 HEAD 和以绿色标出的它和索引之间的区别。 -接下来,`reset`会用 HEAD 指向的当前快照的内容来更新索引。 +接下来,`reset` 会用 HEAD 指向的当前快照的内容来更新索引。 -如果指定`--mixed`选项,`reset`将会在这时停止。 这也是默认行为,所以如果没有指定任何选项(在本例中只是`git reset HEAD~`),这就是命令将会停止的地方。 +如果指定 `--mixed` 选项,`reset` 将会在这时停止。这也是默认行为,所以如果没有指定任何选项(在本例中只是 `git reset HEAD~`),这就是命令将会停止的地方。 -现在再看一眼上图,理解一下发生的事情:它依然会撤销一上次`提交`,但还会**取消暂存**所有的东西。 于是,我们回滚到了所有`git add`和`git commit`的命令执行之前。此时 Index 和 Head 都是v2版本。 +现在再看一眼上图,理解一下发生的事情:它依然会撤销一上次`提交`,但还会**取消暂存**所有的东西。于是,我们回滚到了所有 `git add` 和 `git commit` 的命令执行之前。此时 Index 和 Head 都是 v2 版本。 ### 第 3 步:更新工作目录(--hard) -`reset`要做的的第三件事情就是让工作目录看起来像索引。 如果使用`--hard`选项,它将会把工作区的代码也重置为v2。 +`reset` 要做的的第三件事情就是让工作目录看起来像索引。如果使用 `--hard` 选项,它将会把工作区的代码也重置为 v2。 -到此为止,我们撤销了最后的提交、`git add`和`git commit`命令**以及**工作目录中的所有工作。 +到此为止,我们撤销了最后的提交、`git add` 和 `git commit` 命令**以及**工作目录中的所有工作。 -必须注意,`--hard`标记是`reset`命令唯一的危险用法,它也是 Git 会真正地销毁数据的仅有的几个操作之一。 其他任何形式的`reset`调用都可以轻松撤消,但是`--hard`选项不能,因为它强制覆盖了工作目录中的文件。 在这种特殊情况下,我们的 Git 数据库中的一个提交内还留有该文件的**v3**版本, 我们可以通过`reflog`来找回它。但是若该文件还未提交,Git 仍会覆盖它从而导致无法恢复。 +必须注意,`--hard` 标记是 `reset` 命令唯一的危险用法,它也是 Git 会真正地销毁数据的仅有的几个操作之一。其他任何形式的 `reset` 调用都可以轻松撤消,但是 `--hard` 选项不能,因为它强制覆盖了工作目录中的文件。在这种特殊情况下,我们的 Git 数据库中的一个提交内还留有该文件的 **v3** 版本, 我们可以通过 `reflog` 来找回它。但是若该文件还未提交,Git 仍会覆盖它从而导致无法恢复。 ### **回顾** -`reset`命令会以特定的顺序重写这三棵树,在你指定以下选项时停止: +`reset` 命令会以特定的顺序重写这三棵树,在你指定以下选项时停止: -1. 移动 HEAD 分支的指向**(若指定了**`--soft`,则到此停止) -2. 使 INDEX 看起来像 HEAD**(若未指定**`--hard`,则到此停止) +1. 移动 HEAD 分支的指向(若指定了 `--soft`,则到此停止) +2. 使 INDEX 看起来像 HEAD(若未指定 `--hard`,则到此停止) 3. 使工作目录看起来像 INDEX + ## 通过路径来重置 -前面讲述了`reset`基本形式的行为,不过你还可以给它提供一个作用路径。 若指定了一个路径,`reset`将会跳过第 1 步,并且将它的作用范围限定为指定的文件或文件集合。 因为 HEAD 只是一个指针,你无法让它同时指向两个提交中各自的一部分。 不过索引和工作目录**可以部分更新**,所以重置会继续进行第 2、3 步。 +前面讲述了 `reset` 基本形式的行为,不过你还可以给它提供一个作用路径。若指定了一个路径,`reset` 将会跳过第 1 步,并且将它的作用范围限定为指定的文件或文件集合。因为 HEAD 只是一个指针,你无法让它同时指向两个提交中各自的一部分。不过索引和工作目录**可以部分更新**,所以重置会继续进行第 2、3 步。 -现在,假如我们运行`git reset file.txt`(这其实是`git reset --mixed HEAD file.txt`的简写形式),因为既没有指定一个提交的 SHA-1 或分支,也没有指定`--soft`或`--hard`,所以它会: +现在,假如我们运行 `git reset file.txt`(这其实是 `git reset --mixed HEAD file.txt` 的简写形式),因为既没有指定一个提交的 SHA-1 或分支,也没有指定 `--soft` 或 `--hard`,所以它会: -1. 移动 HEAD 分支的指向**(已跳过)** -2. 让索引看起来像 HEAD**(到此处停止)** +1. 移动 HEAD 分支的指向(已跳过) +2. 让索引看起来像 HEAD(到此处停止) -所以它本质上只是将`file.txt`从 HEAD 复制到索引中。 +所以它本质上只是将 `file.txt` 从 HEAD 复制到索引中。 -它还有**取消暂存文件**的实际效果。 如果我们查看该命令的示意图,然后再想想`git add`所做的事,就会发现它们正好相反。 +它还有**取消暂存文件**的实际效果。 如果我们查看该命令的示意图,然后再想想 `git add` 所做的事,就会发现它们正好相反。 -这就是为什么`git status`命令的输出会建议运行此命令来取消暂存一个文件。 +这就是为什么 `git status` 命令的输出会建议运行此命令来取消暂存一个文件。 -我们可以不让 Git 从 HEAD 拉取数据,而是通过具体指定一个提交来拉取该文件的对应版本。 我们只需运行类似于`git reset 5a56d3 file.txt`的命令即可。 +我们可以不让 Git 从 HEAD 拉取数据,而是通过具体指定一个提交来拉取该文件的对应版本。 我们只需运行类似于 `git reset 5a56d3 file.txt` 的命令即可。 -它其实做了同样的事情,也就是把工作目录中的文件恢复到**v1**版本,运行`git add`添加它, 然后再将它恢复到**v3**版本(只是不用真的过一遍这些步骤)。 如果我们现在运行`git commit`,它就会记录一条“将该文件恢复到**v1**版本”的更改, 尽管我们并未在工作目录中真正地再次拥有它。 +它其实做了同样的事情,也就是把工作目录中的文件恢复到 **v1** 版本,运行 `git add` 添加它, 然后再将它恢复到 **v3** 版本(只是不用真的过一遍这些步骤)。如果我们现在运行 `git commit`,它就会记录一条“将该文件恢复到 **v1** 版本”的更改, 尽管我们并未在工作目录中真正地再次拥有它。 -还有一点同`git add`一样,就是`reset`命令也可以接受一个`--patch`选项来一块一块地取消暂存的内容。 这样你就可以根据选择来取消暂存或恢复内容了。 +还有一点同 `git add` 一样,就是 `reset` 命令也可以接受一个 `--patch` 选项来一块一块地取消暂存的内容。这样你就可以根据选择来取消暂存或恢复内容了。 ## 压缩 -我们来看看如何利用这种新的功能来做一些有趣的事情——压缩提交。 +我们来看看如何利用这种新的功能来做一些有趣的事情 —— 压缩提交。 -假设你的一系列提交信息都是为了一个功能,提交多次显得杂乱,此时可以使用reset将其压缩为一个提交。 +假设你的一系列提交信息都是为了一个功能,提交多次显得杂乱,此时可以使用 reset 将其压缩为一个提交。 -那么可以运行`git reset --soft HEAD~2`来将 HEAD 分支移动到一个旧一点的提交上(即你想要保留的最近的提交),然后只需再次运行`git commit`即可。 +那么可以运行 `git reset --soft HEAD~2` 来将 HEAD 分支移动到一个旧一点的提交上(即你想要保留的最近的提交),然后只需再次运行 `git commit` 即可。 ## 检出 -最后,你大概还想知道`checkout`和`reset`之间的区别。 和`reset`一样,`checkout`也操纵这三个区域,不过它有一点不同,这取决于你是否传给该命令一个文件路径。 +最后,你大概还想知道 `checkout` 和 `reset` 之间的区别。和 `reset` 一样,`checkout` 也操纵这三个区域,不过它有一点不同,这取决于你是否传给该命令一个文件路径。 ### **不带路径** -运行`git checkout [branch]`与运行`git reset --hard [branch]`非常相似,它会更新所有三棵树使其看起来像`[branch]`,不过有两点重要的区别。 +运行 `git checkout [branch]` 与运行 `git reset --hard [branch]` 非常相似,它会更新所有三棵树使其看起来像 `[branch]`,不过有两点重要的区别。 -首先不同于`reset --hard`,`checkout`对工作目录是安全的,它会通过检查来确保不会将已更改的文件弄丢。而`reset --hard`则会不做检查就全面地替换所有东西。 +首先不同于 `reset --hard`,`checkout` 对工作目录是安全的,它会通过检查来确保不会将已更改的文件弄丢。而 `reset --hard` 则会不做检查就全面地替换所有东西。 -第二个重要的区别是`checkout`如何更新 HEAD。`reset`会移动 HEAD 分支的指向,而`checkout`只会移动 HEAD 自身来指向另一个分支。 +第二个重要的区别是 `checkout` 如何更新 HEAD。`reset` 会移动 HEAD 分支的指向,而 `checkout` 只会移动 HEAD 自身来指向另一个分支。 -例如,我们有`master`和`develop`分支,它们分别指向不同的提交;我们现在在`develop`上(所以 HEAD 指向它)。 如果我们运行`git reset master`,那么`develop`自身现在会和`master`指向同一个提交。 而如果我们运行`git checkout master`的话,`develop`不会移动,HEAD 自身会移动。 现在 HEAD 将会指向`master`。 +例如,我们有 `master` 和 `develop` 分支,它们分别指向不同的提交;我们现在在 `develop`上(所以 HEAD 指向它)。 如果我们运行 `git reset master`,那么 `develop` 自身现在会和 `master` 指向同一个提交。 而如果我们运行 `git checkout master` 的话,`develop` 不会移动,HEAD 自身会移动。 现在 HEAD 将会指向 `master`。 -所以,虽然在这两种情况下我们都移动 HEAD 使其指向了提交 A,但做法是不同的。`reset`**会移动 HEAD 分支的指向,而**`checkout`**则移动 HEAD 自身**。 +所以,虽然在这两种情况下我们都移动 HEAD 使其指向了提交 A,但做法是不同的。**`reset` 会移动 HEAD 分支的指向,而`checkout`则移动 HEAD 自身。** ### **带路径** -运行`checkout`的另一种方式就是指定一个文件路径,这会像`reset`一样不会移动 HEAD。 它就像`git reset [branch] file`那样用该次提交中的那个文件来更新索引,但是它也会覆盖工作目录中对应的文件。 它就像是`git reset --hard [branch] file`(如果`reset`允许你这样运行的话), 这样对工作目录并不安全,它也不会移动 HEAD。 +运行 `checkout` 的另一种方式就是指定一个文件路径,这会像 `reset` 一样不会移动 HEAD。 它就像 `git reset [branch] file` 那样用该次提交中的那个文件来更新索引,但是它也会覆盖工作目录中对应的文件。它就像是 `git reset --hard [branch] file`(如果 `reset` 允许你这样运行的话), 这样对工作目录并不安全,它也不会移动 HEAD。 + +此外,同 `git reset` 和 `git add` 一样,`checkout` 也接受一个 `--patch` 选项,允许你根据选择一块一块地恢复文件内容。 -此外,同`git reset`和`git add`一样,`checkout`也接受一个`--patch`选项,允许你根据选择一块一块地恢复文件内容。 \ No newline at end of file diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/8. Rerere.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/8. Rerere.md" index 99b7a8b9ecdb47e969dc6dcd8c22ac68b85c5a78..a55eb799ef037f2a8b7b8641fbe1608bcb3a093b 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/8. Rerere.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/8. Rerere.md" @@ -3,92 +3,99 @@ title: Rerere permalink: /git-tutorial/git-rerere --- -`git rerere`全称是 重用记录的解决方案(reuse recorded resolution)。这个功能是隐藏的,默认不开启。 +`git rerere` 全称是 reuse recorded resolution,即“重用记录的解决方案”。这个功能是隐藏的,默认不开启。 它允许你让 Git 记住解决一个块冲突的方法, 这样在下一次看到相同冲突时,Git 可以为你自动地解决它。 -有些场景下, rerere 会很方便,比如当我们将不同的功能主题分支合并到测试分支,如果测试失败,我们可以将分支回退到合并之前,去除导致测试失败的主题分支后重做合并而不用重新解决所有的冲突。 +有些场景下,rerere 会很方便,比如当我们将不同的功能主题分支合并到测试分支,如果测试失败,我们可以将分支回退到合并之前,去除导致测试失败的主题分支后重做合并而不用重新解决所有的冲突。 ## 示例 -接下来简单的例子: +接下来简单的例子: -1.首先开启 rerere 功能 +1、首先开启 rerere 功能 -`git config --global rerere.enabled true` +```shell +git config --global rerere.enabled true +``` 这是全局开启的设置选项,我们也可以在特定仓库中创建 `.git/rr-cache` 目录来开启功能。 -2.我在 master 分支中创建了一个文件 rerere.txt +2、我在 master 分支中创建了一个文件 rerere.txt,内容为: -内容`rerere master` +```shell +rerere master +``` -3.基于master创建了两个分支 2019 2020 +3、基于 master 创建了两个分支 2019 和 2020 ![图片](./../../../.vuepress/public/images/d9hQAKqRyMuTTuJQ.png) -2019将内容修改为`rerere 2019` +2019 分支将内容修改为 `rerere 2019`,而 2020 分支将内容修改为 `rerere 2020`。 -2020将内容修改为`rerere 2020` - -将两个分支合并 +将两个分支合并: ![图片](./../../../.vuepress/public/images/2tIp9dfvFTfHPtfT.png) -和未开启 rerere 功能的合并冲突相比 +和未开启 rerere 功能的合并冲突相比: ![图片](./../../../.vuepress/public/images/uPCNVrhP9z5CdlDE.png) -多了一行 +多了一行: -`Recorded preimage for 'src/main/resources/rerere.txt'` +```shell +Recorded preimage for 'src/main/resources/rerere.txt' +``` -3.和往常一样,在这个时候你可以运行 git status 来查看所有冲突的内容 +4、和往常一样,在这个时候你可以运行 `git status` 来查看所有冲突的内容 ![图片](./../../../.vuepress/public/images/m6lloArpeoYQFqvJ.png) -也可以用`git rerere status`来查看冲突文件 +也可以用 `git rerere status` 来查看冲突文件: ![图片](./../../../.vuepress/public/images/BAp2ZMP7LeMo92KX.png) -`git rerere diff`将会显示解决方案的当前状态——开始解决前与解决后的样子 +`git rerere diff` 将会显示解决方案的当前状态 —— 开始解决前与解决后的样子: ![图片](./../../../.vuepress/public/images/59i9SdNzZauf39av.png) -4.接受2020的变更,处理冲突后提交,然后在这个文件中制造相同的冲突 - -将2020分支的文件内容修改为`rerere 2021`,提交变更到主分支 +5、接受 2020 分支的变更,处理冲突后提交,然后在这个文件中制造相同的冲突。 -在2019继续合并2020分支,此时正常应该继续提示冲突 +将 2020 分支的文件内容修改为 `rerere 2021`,提交变更到主分支。在 2019 分支继续合并 2020 分支,此时正常应该继续提示冲突。 -但是 +但是: ![图片](./../../../.vuepress/public/images/F2DDnLGpCTpVvadr.png) ![图片](./../../../.vuepress/public/images/rXVwkPcY0ecDZQk9.png) -`Resolved 'src/main/resources/rerere.txt' using previous resolution.` +```shell +Resolved 'src/main/resources/rerere.txt' using previous resolution. +``` -可以看到冲突已经自动解决了,使用了原来的方案 +可以看到冲突已经自动解决了,使用了原来的方案。 -5.`git diff`查看解决方式 +6、`git diff` 查看解决方式 ![图片](./../../../.vuepress/public/images/oZcqjlxI5AHPICFm.png) -6.我们可以使用`checkout`命令恢复合并前状态 +7、我们可以使用 `checkout` 命令恢复合并前状态 -`git checkout --conflict=merge src/main/resources/rerere.txt` +```shell +git checkout --conflict=merge src/main/resources/rerere.txt +``` ![图片](./../../../.vuepress/public/images/K0B6WZkh97YBT6YL.png) -打开 rerere.txt,即可看到合并前内容 +打开 rerere.txt,即可看到合并前内容: ![图片](./../../../.vuepress/public/images/PGSaOe516mGaZrKV.png) -使用`git rerere`将冲突再次解决 +使用 `git rerere` 将冲突再次解决: ![图片](./../../../.vuepress/public/images/GtG8zdGo9FHV2e4Z.png) ## **总结** -`rerere`功能开启后遇到冲突,我们只需解决一遍,当下次遇到相同的冲突,git会帮我们自动处理,即便有些场景不需要它自动合并冲突,我们也可以选择`checkout`将其回退然后手动处理。 +`rerere` 功能开启后遇到冲突,我们只需解决一遍,当下次遇到相同的冲突,git 会帮我们自动处理,即便有些场景不需要它自动合并冲突,我们也可以选择 `checkout` 将其回退然后手动处理。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/9. \344\275\277\347\224\250 Git \350\260\203\350\257\225.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/9. \344\275\277\347\224\250 Git \350\260\203\350\257\225.md" index c221b4db4fdee1496572ad97fa79670152d2ce31..0725a9c721450d02b372db64ba9f3a3e9203325f 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/9. \344\275\277\347\224\250 Git \350\260\203\350\257\225.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/Git \345\267\245\345\205\267/9. \344\275\277\347\224\250 Git \350\260\203\350\257\225.md" @@ -7,9 +7,9 @@ permalink: /git-tutorial/git-debugging ## 文件标注 -文件标注能显示任何文件中每行最后一次修改的提交记录。 所以,如果你在代码中看到一个有 bug 的方法,你可以使用`git blame`标注这个文件,查看哪一次提交引入了这行。 +文件标注能显示任何文件中每行最后一次修改的提交记录。 所以,如果你在代码中看到一个有 bug 的方法,你可以使用 `git blame` 标注这个文件,查看哪一次提交引入了这行。 -以下示例用`git blame`确定了 Linux 内核源码顶层的`Makefile`中每一行分别来自哪个提交和提交者, 此外用`-L`选项还可以将标注的输出限制为该文件中的第 69 行到第 82 行。 +以下示例用 `git blame` 确定了 Linux 内核源码顶层的 `Makefile` 中每一行分别来自哪个提交和提交者,此外用 `-L` 选项还可以将标注的输出限制为该文件中的第 69 行到第 82 行。 ```shell $ git blame -L 69,82 Makefile @@ -28,8 +28,12 @@ b8b0618cf6fab (Cheng Renquan 2009-05-26 16:03:07 +0800 70) KBUILD_VERBOSE = $ 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 81) Q = @ 066b7ed955808 (Michal Marek 2014-07-04 14:29:30 +0200 82) endif ``` -请注意,第一个字段是最后一次修改该行的提交的部分 SHA-1 值。 接下来两个字段的值是从提交中提取出来的——作者的名字以及提交的时间——所以你就可以很轻易地知道是谁在什么时候修改了那一行。 接下来就是行号和文件内容。 注意一下`^1da177e4c3f4`这个提交的几行,其中的前缀`^`指出了该文件自第一次提交后从未修改的那些行。 -另一件比较酷的事情是 Git 不会显式地记录文件的重命名。 它会记录快照,然后在事后尝试计算出重命名的动作。 这其中有一个很有意思的特性就是你可以让 Git 找出所有的代码移动。 如果你在`git blame`后面加上一个`-C`,Git 会分析你正在标注的文件, 并且尝试找出文件中从别的地方复制过来的代码片段的原始出处。 比如,你将`GITServerHandler.m`这个文件拆分为数个文件,其中一个文件是`GITPackUpload.m`。 对`GITPackUpload.m`执行带`-C`参数的 blame 命令,你就可以看到代码块的原始出处: + +请注意,第一个字段是最后一次修改该行的提交的部分 SHA-1 值。接下来两个字段的值是从提交中提取出来的 —— 作者的名字以及提交的时间 —— 所以你就可以很轻易地知道是谁在什么时候修改了那一行。接下来就是行号和文件内容。 注意一下 `^1da177e4c3f4` 这个提交的几行,其中的前缀 `^` 指出了该文件自第一次提交后从未修改的那些行。 + +另一件比较酷的事情是 Git 不会显式地记录文件的重命名。它会记录快照,然后在事后尝试计算出重命名的动作。这其中有一个很有意思的特性就是你可以让 Git 找出所有的代码移动。如果你在 `git blame` 后面加上一个 `-C`,Git 会分析你正在标注的文件,并且尝试找出文件中从别的地方复制过来的代码片段的原始出处。 + +比如,你将 `GITServerHandler.m` 这个文件拆分为数个文件,其中一个文件是 `GITPackUpload.m`。对 `GITPackUpload.m` 执行带 `-C` 参数的 blame 命令,你就可以看到代码块的原始出处: ```shell $ git blame -C -L 141,153 GITPackUpload.m @@ -47,12 +51,14 @@ ad11ac80 GITPackUpload.m (Scott 2009-03-24 150) 56ef2caf GITServerHandler.m (Scott 2009-01-05 152) [refDict setOb 56ef2caf GITServerHandler.m (Scott 2009-01-05 153) ``` -这个功能很有用。 通常来说,你会认为复制代码过来的那个提交是最原始的提交,因为那是你第一次在这个文件中修改了这几行。 但 Git 会告诉你,你第一次写这几行代码的那个提交才是原始提交,即使这是在另外一个文件里写的。 + +这个功能很有用。通常来说,你会认为复制代码过来的那个提交是最原始的提交,因为那是你第一次在这个文件中修改了这几行。但 Git 会告诉你,你第一次写这几行代码的那个提交才是原始提交,即使这是在另外一个文件里写的。 + ## 二分查找 -当你知道问题是在哪里引入的情况下文件标注可以帮助你查找问题。 如果你不知道哪里出了问题,并且自从上次可以正常运行到现在已经有数十个或者上百个提交, 这个时候你可以使用`git bisect`来帮助查找。`bisect`命令会对你的提交历史进行二分查找来帮助你尽快找到是哪一个提交引入了问题。 +当你知道问题是在哪里引入的情况下文件标注可以帮助你查找问题。 如果你不知道哪里出了问题,并且自从上次可以正常运行到现在已经有数十个或者上百个提交, 这个时候你可以使用 `git bisect` 来帮助查找。`bisect` 命令会对你的提交历史进行二分查找来帮助你尽快找到是哪一个提交引入了问题。 -首先执行`git bisect start`来启动,接着执行`git bisect bad`来告诉系统当前你所在的提交是有问题的。 然后你必须使用`git bisect good `,告诉 bisect 已知的最后一次正常状态是哪次提交: +首先执行 `git bisect start` 来启动,接着执行 `git bisect bad` 来告诉系统当前你所在的提交是有问题的。然后你必须使用 `git bisect good `,告诉 bisect 已知的最后一次正常状态是哪次提交: ```shell $ git bisect start @@ -61,19 +67,25 @@ $ git bisect good v1.0 Bisecting: 6 revisions left to test after this [ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo ``` -Git 发现在你标记为正常的提交(v1.0)和当前的错误版本之间有大约12次提交,于是 Git 检出中间的那个提交。 现在你可以执行测试,看看在这个提交下问题是不是还是存在。 如果还存在,说明问题是在这个提交之前引入的;如果问题不存在,说明问题是在这个提交之后引入的。 假设测试结果是没有问题的,你可以通过`git bisect good`来告诉 Git,然后继续寻找。 + +Git 发现在你标记为正常的提交(v1.0)和当前的错误版本之间有大约 12 次提交,于是 Git 检出中间的那个提交。现在你可以执行测试,看看在这个提交下问题是不是还是存在。如果还存在,说明问题是在这个提交之前引入的;如果问题不存在,说明问题是在这个提交之后引入的。假设测试结果是没有问题的,你可以通过 `git bisect good` 来告诉 Git,然后继续寻找。 + ```shell $ git bisect good Bisecting: 3 revisions left to test after this [b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing ``` -现在你在另一个提交上了,这个提交是刚刚那个测试通过的提交和有问题的提交的中点。 你再一次执行测试,发现这个提交下是有问题的,因此你可以通过`git bisect bad`告诉 Git: + +现在你在另一个提交上了,这个提交是刚刚那个测试通过的提交和有问题的提交的中点。你再一次执行测试,发现这个提交下是有问题的,因此你可以通过 `git bisect bad` 告诉 Git: + ```shell $ git bisect bad Bisecting: 1 revisions left to test after this [f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table ``` -这个提交是正常的,现在 Git 拥有的信息已经可以确定引入问题的位置在哪里。 它会告诉你第一个错误提交的 SHA-1 值并显示一些提交说明,以及哪些文件在那次提交里被修改过,这样你可以找出引入 bug 的根源: + +这个提交是正常的,现在 Git 拥有的信息已经可以确定引入问题的位置在哪里。它会告诉你第一个错误提交的 SHA-1 值并显示一些提交说明,以及哪些文件在那次提交里被修改过,这样你可以找出引入 bug 的根源: + ```shell $ git bisect good b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit @@ -84,22 +96,29 @@ secure this thing :040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730 f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M config ``` -当你完成这些操作之后,你应该执行`git bisect reset`重置你的 HEAD 指针到最开始的位置, 否则你会停留在一个奇怪的状态: + +当你完成这些操作之后,你应该执行 `git bisect reset` 重置你的 HEAD 指针到最开始的位置,否则你会停留在一个奇怪的状态: + ```shell $ git bisect reset ``` -这是一个可以帮助你在几分钟内从数百个提交中找到 bug 的强大工具。 事实上,如果你有一个脚本在项目是正常的情况下返回 0,在不正常的情况下返回非 0,你可以使`git bisect`自动化这些操作。 首先,你设定好项目正常以及不正常所在提交的二分查找范围。 你可以通过`bisect start`命令的参数来设定这两个提交,第一个参数是项目不正常的提交,第二个参数是项目正常的提交: + +这是一个可以帮助你在几分钟内从数百个提交中找到 bug 的强大工具。事实上,如果你有一个脚本在项目是正常的情况下返回 0,在不正常的情况下返回非 0,你可以使 `git bisect` 自动化这些操作。首先,你设定好项目正常以及不正常所在提交的二分查找范围。你可以通过 `bisect start` 命令的参数来设定这两个提交,第一个参数是项目不正常的提交,第二个参数是项目正常的提交: + ```shell $ git bisect start HEAD v1.0 $ git bisect run test-error.sh ``` -Git 会自动在每个被检出的提交里执行`test-error.sh`,直到找到项目第一个不正常的提交。 你也可以执行`make`或者`make tests`或者其他东西来进行自动化测试。 + +Git 会自动在每个被检出的提交里执行 `test-error.sh`,直到找到项目第一个不正常的提交。你也可以执行 `make` 或者 `make tests` 或者其他东西来进行自动化测试。 + ## 应用 -实际上 Git 和 IDEA 集成后,有更方便的方式查看提交记录,直接右键选择 +实际上 Git 和 IDEA 集成后,有更方便的方式查看提交记录,直接右键选择。 ![图片](./../../../.vuepress/public/images/bmANMHF927G3NyZr.png) 然后就可以看到这行代码最新提交人了。双击这行提交记录,还可以看到这位开发者在这次提交中提交的其他文件和记录,方便找问题源头和甩锅。 -![图片](./../../../.vuepress/public/images/WJ7sn0bFoe7xyipn.png) \ No newline at end of file +![图片](./../../../.vuepress/public/images/WJ7sn0bFoe7xyipn.png) + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/1. \344\273\200\344\271\210\346\230\257 GitOps.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/1. \344\273\200\344\271\210\346\230\257 GitOps.md" index cf2a002e53c12e53d323ce984217138f4533b6c3..686d0aa66ad85952bd8f9cbc1cef4fde5741a366 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/1. \344\273\200\344\271\210\346\230\257 GitOps.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/1. \344\273\200\344\271\210\346\230\257 GitOps.md" @@ -2,26 +2,24 @@ title: 什么是 GitOps permalink: /git-tutorial/what-is-gitops --- + 随着 DevOps 以及 GitOps 之类辅助实践的兴起,软件从架构设计到代码被部署到生产环境的速度是越来越快。 ->DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运维和质量保障(QA)部门之间的沟通、协作与整合 +> DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运维和质量保障(QA)部门之间的沟通、协作与整合。 DevOps 通过实践和规范来提高我们生成代码的速度,并保证代码的可靠性。 -GitOps 是在具体Kubernetes的应用实践中出现的, 具体定义是 Alexis 在 2017 年 8 月发表的一篇[博客](https://www.weave.works/blog/gitops-operations-by-pull-request),这篇文章中第一次提到了 GitOps 的概念和他们的实践应用。 +GitOps 是在具体Kubernetes的应用实践中出现的, 具体定义是 Alexis 在2017年8月发表的一篇[博客](https://www.weave.works/blog/gitops-operations-by-pull-request),这篇文章中第一次提到了 GitOps 的概念和他们的实践应用。 ->我们的整个系统状态都在版本控制之下,并在一个单一的 Git 仓库中进行描述。 ->操作上的改变是通过 pull request (加上构建和发布管道)来进行的 ->Diff 工具可以检测到任何分歧,并通过 Slack 警报通知我们;同步工具可以实现收敛 ->还通过 Git 提供回滚和审计日志。 +> 我们的整个系统状态都在版本控制之下,并在一个单一的 Git 仓库中进行描述。操作上的改变是通过 pull request (加上构建和发布管道)来进行的;Diff 工具可以检测到任何分歧,并通过 Slack 警报通知我们;同步工具可以实现收敛。还通过 Git 提供回滚和审计日志。 -GitOps 是一种做持续交付的方式。 它的工作原理是将 Git 作为声明式基础架构和应用的核心。当 Git 发生变化时,自动交付管道会自动将版本改动推包。 但这个想法更进一步--使用工具来查看实际的生产状态,并告诉你什么时候的源代码与真实世界不一致,让你有能力发现差异并相应地解决问题。 换句话说, GitOps 扩展了管道,有一个观察和控制系统的反馈循环 。 +GitOps 是一种做持续交付的方式。它的工作原理是将 Git 作为声明式基础架构和应用的核心。当 Git 发生变化时,自动交付管道会自动将版本改动推包。但这个想法更进一步--使用工具来查看实际的生产状态,并告诉你什么时候的源代码与真实世界不一致,让你有能力发现差异并相应地解决问题。换句话说,GitOps 扩展了管道,有一个观察和控制系统的反馈循环 。 ## 主要优点 主要优点就是 GitOps 赋予开发者做运维的权力。 -为了做到这一点,GitOps 旨在通过将熟悉的工具应用于困难的事情:运维管理和监控,从而提高开发人员的工作效率。 每个开发者都可以使用 Git 并进行拉取请求;现在他们可以使用 Git 来加速和简化 Kubernetes 等的运维任务。 其好处是深远的。 +为了做到这一点,GitOps 旨在通过将熟悉的工具应用于困难的事情:运维管理和监控,从而提高开发人员的工作效率。 每个开发者都可以使用 Git 并进行拉取请求;现在他们可以使用 Git 来加速和简化 Kubernetes 等的运维任务。其好处是深远的。 一个云原生 CICD 管道的模型。 @@ -35,6 +33,7 @@ GitOps 是一种做持续交付的方式。 它的工作原理是将 Git 作为 ## 应用场景 -在Alexis的第二篇[文章](https://www.weave.works/blog/the-gitops-pipeline)中介绍了 GitOps 是持续交付与云原生的结合( GitOps is Continuous Delivery meets Cloud Native ) +在 Alexis 的第二篇[文章](https://www.weave.works/blog/the-gitops-pipeline)中介绍了 GitOps 是持续交付与云原生的结合(GitOps is Continuous Delivery meets Cloud Native)。 GitOps 作为一个流水线方案,没有一个单一工具可以完成整条流水线,所以需要去组合开源甚至闭源的工具,它的优势也是在各个功能节点自由的选择最适合的,所以困难的地方就是将部件粘合在一起。 + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/2. \344\273\243\347\240\201\350\257\204\345\256\241\345\271\263\345\217\260\347\232\204\346\220\255\345\273\272\344\270\216\344\275\277\347\224\250.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/2. \344\273\243\347\240\201\350\257\204\345\256\241\345\271\263\345\217\260\347\232\204\346\220\255\345\273\272\344\270\216\344\275\277\347\224\250.md" index d05725b25a9841e1ed72082038da4e9ea6bb126d..027cb1fbde6b8a12f53ad6573779f0019636d1ce 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/2. \344\273\243\347\240\201\350\257\204\345\256\241\345\271\263\345\217\260\347\232\204\346\220\255\345\273\272\344\270\216\344\275\277\347\224\250.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/2. \344\273\243\347\240\201\350\257\204\345\256\241\345\271\263\345\217\260\347\232\204\346\220\255\345\273\272\344\270\216\344\275\277\347\224\250.md" @@ -2,45 +2,48 @@ title: 代码评审平台的搭建与使用 permalink: /git-tutorial/code-review --- -可能不同的公司有自己的`code review`方式,我们以前还经常开评审会,首先约会议并通知评审的范围和开发成员,然后快下班甚至下了班的时候去做这些事情,当时也都戏称为公开处刑,给待审查的成员较大的压力,生怕有低级错误出现,这种方式也浪费了团队不少的时间。 -## GitLab 提供了一种很棒的方式,就是利用 Merge Request 做代码评审 +可能不同的公司有自己的 Code Review 方式,我们以前还经常开评审会,首先约会议并通知评审的范围和开发成员,然后快下班甚至下了班的时候去做这些事情,当时也都戏称为公开处刑,给待审查的成员较大的压力,生怕有低级错误出现,这种方式也浪费了团队不少的时间。 -比如我们修改了一个问题提交推送到了自己的分支,然后需要新增一个合并请求 merge request 将改动合并到开发测试 develop 分支 +## 利用 Merge Request 做代码评审 -![图片](./../../../.vuepress/public/images/Hh9bNJbCIt6HiLux.png) +GitLab 提供了一种很棒的方式,就是利用 Merge Request 做代码评审。 + +比如我们修改了一个问题提交推送到了自己的分支,然后需要新增一个合并请求 merge request 将改动合并到开发测试 develop 分支。 +![图片](./../../../.vuepress/public/images/Hh9bNJbCIt6HiLux.png) ![图片](./../../../.vuepress/public/images/fc0IXF0Lq8NsKXoS.png) -填写描述和想要指定的审查者 +填写描述和想要指定的审查者: ![图片](./../../../.vuepress/public/images/MREFzVlqAh7eexOR.png) -审查者看到需要审查的合并提交 +审查者看到需要审查的合并提交: ![图片](./../../../.vuepress/public/images/JgqrYuzntCGIo0p2.png) ![图片](./../../../.vuepress/public/images/7CAtqhc2sHwkXXjM.png) -审查者可以对合并进行评论,甚至是对每行代码进行注释标注 +审查者可以对合并进行评论,甚至是对每行代码进行注释标注: ![图片](./../../../.vuepress/public/images/VnJna2KOQNQtAaTW.png) -[https://gitlab.com/gitlab-com/www-gitlab-com/](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/62887) +这里有个官方的线上例子可以点点看([https://gitlab.com/gitlab-com/www-gitlab-com/](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/62887))。 -这里有个官方的线上例子可以点点看 -## 类似的,使用 GitHub 和 Gitee 的 pull request 进行代码审查 +## 使用 Pull Request 进行代码审查 -### **1.仓库管理员设置代码审查** +类似的,使用 GitHub 和 Gitee 的 Pull Request 进行代码审查。 -代码审查以仓库为单位,根据需求设置相应的代码审核/测试人员 +### 仓库管理员设置代码审查 + +代码审查以仓库为单位,根据需求设置相应的代码审核/测试人员。 ![图片](./../../../.vuepress/public/images/QPnQA7iuz9JbE1SC.png) -### **2.开发者提交 Pull Request** +### 开发者提交 Pull Request 开发者 Fork 目标仓库,在对应分支上修改后,推送到自己 Fork 的仓库里,从自己仓库中点击“+ Pull Request”。 @@ -50,15 +53,15 @@ permalink: /git-tutorial/code-review ![图片](./../../../.vuepress/public/images/aoOkpwqEVDhHBmPY.png) -### **3.审查者进行代码审核/测试** +### 审查者进行代码审核/测试 -审查者可以在 pull request 中看到信息和代码修改详情 +审查者可以在 Pull Request 中看到信息和代码修改详情。 ![图片](./../../../.vuepress/public/images/gYmK9yfenzko0Wyn.png) ![图片](./../../../.vuepress/public/images/7Z2a0ZbA5dHKMCuW.png) -审查者可以在“评论”中留下自己对这个 Pull Request 中改动的意见和建议,同时支持“文件改动”中对代码行注释 +审查者可以在“评论”中留下自己对这个 Pull Request 中改动的意见和建议,同时支持“文件改动”中对代码行注释。 ![图片](./../../../.vuepress/public/images/ZbONNypu3y04Qu6G.png) @@ -66,8 +69,9 @@ permalink: /git-tutorial/code-review 审查者的建议会通过站内信等方式通知提交 Pull Request 的开发者,开发者可以根据情况在“评论”中与审查者进行讨论。 -### **4.仓库管理员合并 Pull Request** +### 仓库管理员合并 Pull Request -​Pull Request 代码审查完成且满足仓库管理员设置的代码审查规则后,可由管理员把这个 Pull Request 合并到目标分支。合并完成后,开发者对目标分支的改动就生效了。 +Pull Request 代码审查完成且满足仓库管理员设置的代码审查规则后,可由管理员把这个 Pull Request 合并到目标分支。合并完成后,开发者对目标分支的改动就生效了。 ![图片](./../../../.vuepress/public/images/f0qGFXcFlI3Jfrza.png) + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/3. \344\270\216 Jenkins , Nexus , Ansible \347\255\211\346\225\264\345\220\210.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/3. \344\270\216 Jenkins , Nexus , Ansible \347\255\211\346\225\264\345\220\210.md" index 0c647409d8d04240944faf9da6a359769f552b58..0284f999546a50d3c24500c6a7c7ef9d9cdee38a 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/3. \344\270\216 Jenkins , Nexus , Ansible \347\255\211\346\225\264\345\220\210.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/GitOps/3. \344\270\216 Jenkins , Nexus , Ansible \347\255\211\346\225\264\345\220\210.md" @@ -1,100 +1,98 @@ --- -title: 与 Jenkins , Nexus , Ansible 等整合 +title: 与 Jenkins、Nexus、Ansible 工具等整合 permalink: /git-tutorial/integrate-jenkins-nexus-ansible --- -## 工具 -首先介绍下这些工具是干什么的: - -Jenkins CI/CD 基于Java开发的持续集成工具 - -Nexus 依赖仓库    Maven仓库管理器 +## 工具介绍 -Ansible 自动化运维工具   基于Python开发的自动化运维工具 +首先介绍下这些工具是干什么的: -Gitee/GitHub/GitLab 代码管理 +- Jenkins CI/CD:基于Java开发的持续集成工具; +- Nexus:依赖仓库,Maven 仓库管理器; +- Ansible:自动化运维工具,基于 Python 开发的自动化运维工具; +- Gitee/GitHub/GitLab:代码管理工具/平台。 ## 整合 Demo ### 1. Jenkins 中 Maven 配置 -Jenkins → Global Tool Configuration +Jenkins --> Global Tool Configuration ![图片](./../../../.vuepress/public/images/6wp82eLM7PaC6JRS.png) - - ![图片](./../../../.vuepress/public/images/p32jHEAF02u4K88J.png) -### 2.在代码仓库新建一个 Maven 的 Hello World 项目 +### 2. 新建 Maven 仓库 + +在代码仓库新建一个 Maven 的 Hello World 项目。 ![图片](./../../../.vuepress/public/images/RbJ4K4JeubIqN787.png) -### 3.在 Jenkins 中新建 Item +### 3. 在 Jenkins 中新建 Item -1.新建 +1. **新建** -![图片](./../../../.vuepress/public/images/6aMhvYrboHTWPcIx.png) + ![图片](./../../../.vuepress/public/images/6aMhvYrboHTWPcIx.png) -2.添加描述 +2. **添加描述** -![图片](./../../../.vuepress/public/images/PxqylA9QyweagTXN.png) + ![图片](./../../../.vuepress/public/images/PxqylA9QyweagTXN.png) -3.源码管理配置仓库地址和凭证信息 +3. **源码管理配置仓库地址和凭证信息** -![图片](./../../../.vuepress/public/images/qNtYN9xvA0B7nS8R.png) + ![图片](./../../../.vuepress/public/images/qNtYN9xvA0B7nS8R.png) -4.新增构建设置 +4. **新增构建设置** -使用 maven 构建 + 使用 maven 构建: -![图片](./../../../.vuepress/public/images/nOkjIMwTAzN1nal9.png) + ![图片](./../../../.vuepress/public/images/nOkjIMwTAzN1nal9.png) -或者使用 ansible 执行剧本构建 + 或者使用 ansible 执行剧本构建。 -如果 ansible 有单独服务器,则需要安装 SSH 插件,远程 SSH 执行剧本 + 如果 ansible 有单独服务器,则需要安装 SSH 插件,远程 SSH 执行脚本: -![图片](./../../../.vuepress/public/images/EJD6Z9YTCj1qPGQC.png) + ![图片](./../../../.vuepress/public/images/EJD6Z9YTCj1qPGQC.png) -5.构建后操作 +5. **构建后操作** -写了个重启脚本,拿到当前执行项目的 pid,kill,然后 nohup 重启程序的 jar + 写了个重启脚本,拿到当前执行项目的 pid,kill,然后 `nohup` 重启程序的 jar。 -![图片](./../../../.vuepress/public/images/14rfmbHaL7AWuNbW.png) + ![图片](./../../../.vuepress/public/images/14rfmbHaL7AWuNbW.png) -6.构建触发器 +6. **构建触发器** -### **Gitee** +#### Gitee 平台配置 -Gitee文档:[https://gitee.com/help/articles/4183](https://gitee.com/help/articles/4183) +Gitee 文档:[https://gitee.com/help/articles/4183](https://gitee.com/help/articles/4183) -安装 Gitee 插件 +安装 Gitee 插件: ![图片](./../../../.vuepress/public/images/Kfj56rspKO4Ow5Jw.png) -选择需要触发构建的策略 +选择需要触发构建的策略: ![图片](./../../../.vuepress/public/images/H1r9l7blTdVr1Zkw.png) -添加 WebHooks +添加 WebHooks: ![图片](./../../../.vuepress/public/images/3d7q0uzFhN7JTmwl.png) ![图片](./../../../.vuepress/public/images/rsvaM3hXGsE58nhV.png) -### **GitHub** +#### GitHub 平台配置 -类似的安装 pull request 插件![图片](./../../../.vuepress/public/images/oPUmuVdhQwrACLEb.png) +类似的安装 pull request 插件: -然后配置 +![图片](./../../../.vuepress/public/images/oPUmuVdhQwrACLEb.png) -![图片](./../../../.vuepress/public/images/2R6SxJWKdCBuBh8q.png) +然后配置: -登录 GitHub,Settings>>Webhooks 中,此时会生成一个新的 webhook +![图片](./../../../.vuepress/public/images/2R6SxJWKdCBuBh8q.png) -也是选择自己需要触发构建的策略后保存 +登录 GitHub,Settings>>Webhooks 中,此时会生成一个新的 webhook,也是选择自己需要触发构建的策略后保存。 -4.测试构建是否正常 +### 4. 测试构建是否正常 ![图片](./../../../.vuepress/public/images/EODOUdTulqSEfSSe.png) @@ -102,6 +100,7 @@ Gitee文档:[https://gitee.com/help/articles/4183](https://gitee.com/help/arti ## 总结 -根据配置的触发策略,开发者完成一个任务,提交 pull request 或者 管理者代码审查后 合并 request ,会触发 Jenkins 构建并自动发布重启项目,减少了团队手动运维的时间成本。 +根据配置的触发策略,开发者完成一个任务,提交 Pull Request 或者管理者代码审查后合并 PR,会触发 Jenkins 构建并自动发布重启项目,减少了团队手动运维的时间成本。 + +以上只是 GitOps 的一个简单例子,实际上不限于以上这些工具,Jenkins 有一个 [JenkinsX](https://jenkins-x.io/docs/) 的版本专门为 GitOps 而生,也可以将 Jenkins 换成 [Argo CD](https://argoproj.github.io/argo-cd/) 等。 -以上只是 GitOps 的一个简单例子,实际上不限于以上这些工具,Jenkins 有一个[JenkinsX](https://jenkins-x.io/docs/)的版本专门为 GitOps 而生,也可以将 Jenkins 换成[Argo CD](https://argoproj.github.io/argo-cd/)等。 diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/1. \345\210\206\345\270\203\345\274\217\345\267\245\344\275\234\346\265\201\347\250\213.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/1. \345\210\206\345\270\203\345\274\217\345\267\245\344\275\234\346\265\201\347\250\213.md" index 8058de50e0f6d87791060c32805b619ff385fbe6..1e6d801fabcf563b1bd674e31ece98dbdda06668 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/1. \345\210\206\345\270\203\345\274\217\345\267\245\344\275\234\346\265\201\347\250\213.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/1. \345\210\206\345\270\203\345\274\217\345\267\245\344\275\234\346\265\201\347\250\213.md" @@ -11,38 +11,38 @@ permalink: /git-tutorial/distributed-workflow ## 分布式管理 -使用Git做开发时,`git clone`克隆一个本地版本,然后在本地进行操作提交,本地可以完成一个完整的版本控制。只需要在发布前,使用`git push`推送到远程即可。 +使用Git做开发时,`git clone` 克隆一个本地版本,然后在本地进行操作提交,本地可以完成一个完整的版本控制。只需要在发布前,使用 `git push` 推送到远程即可。 ## 集中式工作流程 -一般来讲,Git管理的项目,有一个默认分支master,这个分支只负责版本发布,一般不给开发者直接提交或删除权限,有的项目也将这个分支叫发布分支--release +一般来讲,Git 管理的项目,有一个默认分支 **master**,这个分支只负责版本发布,一般不给开发者直接提交或删除权限,有的项目也将这个分支叫发布分支 —— **release**。 -实际开发的分支都是develop分支或者基于develop分支的其他版本需求分支上完成。 +实际开发的分支都是 develop 分支或者基于 develop 分支的其他版本需求分支上完成。 -比如说现有A,B,C三个程序开发者,然后他们每个人都有自己的需求a1,a2,b,c +比如说现有 A,B,C 三个程序开发者,然后他们每个人都有自己的需求 a1,a2,b,c。 -他们各自从develop分支基础上建立自己的分支,因为考虑到需求是否会被延期,A建立了两个分支分别用来开发需求a1,a2。三位的需求开发完成后,各自将自己的分支合并到develop上,在发布前由测试或者专人将develop合并到release分支上进行最后的代码扫描分析等等,最后以release分支为发布基准。 +他们各自从 develop 分支基础上建立自己的分支,因为考虑到需求是否会被延期,A 建立了两个分支分别用来开发需求 a1,a2。三位的需求开发完成后,各自将自己的分支合并到 develop 上,在发布前由测试或者专人将 develop 合并到 release 分支上进行最后的代码扫描分析等等,最后以 release 分支为发布基准。 ![图片](./../../../.vuepress/public/images/gM53Yyu9gFIUDalD.png) -如果B和C两位虽然是不同的需求,但是他们修改了同一行的代码,如果B先向develop发起合并而且成功了,那么C发起合并请求时会遭到服务器拒绝,只有合并文件修改后才可以继续推送。 +如果 B 和 C 两位虽然是不同的需求,但是他们修改了同一行的代码,如果 B 先向 develop 发起合并而且成功了,那么 C 发起合并请求时会遭到服务器拒绝,只有合并文件修改后才可以继续推送。 这是一种应用广泛的工作流程。 ## 集成管理者工作流 -Git 允许多个远程仓库存在,使得这样一种工作流成为可能:每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。 这种情形下通常会有个代表“官方”项目的权威的仓库。 要为这个项目做贡献,你需要从该项目克隆出一个自己的公开仓库,然后将自己的修改推送上去。 接着你可以请求官方仓库的维护者拉取更新合并到主项目。 维护者可以将你的仓库作为远程仓库添加进来,在本地测试你的变更,将其合并入他们的分支并推送回官方仓库。 +Git 允许多个远程仓库存在,使得这样一种工作流成为可能:每个开发者拥有自己仓库的写权限和其他所有人仓库的读权限。这种情形下通常会有个代表“官方”项目的权威的仓库。要为这个项目做贡献,你需要从该项目克隆出一个自己的公开仓库,然后将自己的修改推送上去。接着你可以请求官方仓库的维护者拉取更新合并到主项目。维护者可以将你的仓库作为远程仓库添加进来,在本地测试你的变更,将其合并入他们的分支并推送回官方仓库。 这是 GitHub 和 Gitee 等集线器式(hub-based)工具最常用的工作流程。 -人们可以容易地将某个项目派生成为自己的公开仓库,向这个仓库推送自己的修改,并为每个人所见。 这么做最主要的优点之一是你可以持续地工作,而主仓库的维护者可以随时拉取你的修改。 贡献者不必等待维护者处理完提交的更新——每一方都可以按照自己的节奏工作。 +人们可以容易地将某个项目派生成为自己的公开仓库,向这个仓库推送自己的修改,并为每个人所见。这么做最主要的优点之一是你可以持续地工作,而主仓库的维护者可以随时拉取你的修改。贡献者不必等待维护者处理完提交的更新——每一方都可以按照自己的节奏工作。 ![图片](./../../../.vuepress/public/images/Lk6S4PuSg9BfBZ20.png) -为了方便阅读,我用A账号在Gitee上建了一个仓库`https://gitee.com/willcoder/GitTest.git` +为了方便阅读,我用 A 账号在 Gitee 上建了一个仓库 `https://gitee.com/willcoder/GitTest.git`。 -使用B账号作为贡献者来做个简单例子。 +使用 B 账号作为贡献者来做个简单例子。 1. 项目维护者推送到主仓库。 @@ -50,36 +50,36 @@ Git 允许多个远程仓库存在,使得这样一种工作流成为可能: 里面随便塞了几个文件。 -1. 贡献者克隆此仓库,做出修改。 +2. 贡献者克隆此仓库,做出修改。 -因为B账号没有权限push这个项目,所以对仓库进行fork +因为 B 账号没有权限 push 这个项目,所以对仓库进行 fork。 ![图片](./../../../.vuepress/public/images/QDaBa4jnHHcDc2T0.png) -克隆代码后,新增了一个文件 +克隆代码后,新增了一个文件: ![图片](./../../../.vuepress/public/images/14G2iFWYNeI17b0F.png) -3.贡献者发送pull request +3. 贡献者发送 pull request。 ![图片](./../../../.vuepress/public/images/0x7bSxcEmkGYik4Z.png) -填写内容和说明 +填写内容和说明: ![图片](./../../../.vuepress/public/images/iH5UWF4eWtAQPgiN.png) -4.维护者在自己本地的仓库中,将贡献者的仓库加为远程仓库并合并修改。 +4. 维护者在自己本地的仓库中,将贡献者的仓库加为远程仓库并合并修改。 ![图片](./../../../.vuepress/public/images/zxA3sQemgLMYhODe.png) -审查测试后即可合并请求 +审查测试后即可合并请求: ![图片](./../../../.vuepress/public/images/JJ2oJdwB0yLkEvLO.png) ## 司令官与副官工作流 -这其实是多仓库工作流程的变种。 可以按照字面意思理解,或者结合一家公司的组织架构来看,由总经理,各个部门的分管总以及分管总下的普通员工这三个级别,总经理统筹大局,负责对外的主分支维护合并等工作,分管总负责这个大型项目的特定范围,处理下面普通开发者提交的该范围的请求。 +这其实是多仓库工作流程的变种。可以按照字面意思理解,或者结合一家公司的组织架构来看,由总经理,各个部门的分管总以及分管总下的普通员工这三个级别,总经理统筹大局,负责对外的主分支维护合并等工作,分管总负责这个大型项目的特定范围,处理下面普通开发者提交的该范围的请求。 -一般拥有数百位协作开发者的超大型项目才会用到这样的工作方式,例如著名的 Linux 内核项目。 被称为 副主管(lieutenant) 的各个集成管理者分别负责集成项目中的特定部分。 所有这些副主管头上还有一位称为 主管(dictator) 的总集成管理者负责统筹。 主管维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。 +一般拥有数百位协作开发者的超大型项目才会用到这样的工作方式,例如著名的 Linux 内核项目。 被称为 **副主管**(lieutenant)的各个集成管理者分别负责集成项目中的特定部分。所有这些副主管头上还有一位称为 **主管**(dictator)的总集成管理者负责统筹。主管维护的仓库作为参考仓库,为所有协作者提供他们需要拉取的项目代码。 -这种工作流并不常用,只有当项目极为庞杂,或者需要多级别管理时,才会体现出优势。 \ No newline at end of file +这种工作流并不常用,只有当项目极为庞杂,或者需要多级别管理时,才会体现出优势。 diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/2. \345\220\221\344\270\200\344\270\252\351\241\271\347\233\256\350\264\241\347\214\256.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/2. \345\220\221\344\270\200\344\270\252\351\241\271\347\233\256\350\264\241\347\214\256.md" index ed223893235f6205dfc572dabb62f99b8773e8a6..cf2c038fc6c61a42beed96b74be8d0a1634ee0cd 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/2. \345\220\221\344\270\200\344\270\252\351\241\271\347\233\256\350\264\241\347\214\256.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/2. \345\220\221\344\270\200\344\270\252\351\241\271\347\233\256\350\264\241\347\214\256.md" @@ -5,58 +5,53 @@ permalink: /git-tutorial/contribute-to-a-project ## 私有化团队 -一般都会采用类似 SVN 的集中式工作流程。说白了,就是几个程序员共同在master分支上做开发。对于快速迭代,成员少的小项目来说,不失为一种好用的方式。 +一般都会采用类似 SVN 的集中式工作流程。说白了,就是几个程序员共同在 master 分支上做开发。对于快速迭代,成员少的小项目来说,不失为一种好用的方式。 -每个人都将远程仓库clone到本地,开发各自的功能 +每个人都将远程仓库 clone 到本地,开发各自的功能。 -然后经过`git add`-->`git commit -m 'msg'`-->`git push`到远程仓库。 +然后经过 `git add` --> `git commit -m 'msg'` --> `git push` 到远程仓库。 +示例:新建项目 [fake-project](https://gitee.com/willcoder/fake-project)。 - -eg:新建项目[https://gitee.com/willcoder/fake-project.git](https://gitee.com/willcoder/fake-project.git) - -现有甲乙两人,他们都克隆了项目,并且分别改了新增和修改的脚本文件并提交,此时没有任何问题 +现有甲乙两人,他们都克隆了项目,并且分别改了新增和修改的脚本文件并提交,此时没有任何问题。 ``` git clone https://gitee.com/willcoder/fake-project.git ``` + ![图片](./../../../.vuepress/public/images/5i0BojJOgCvE2sAk.png) -如果二人同时修改了delete脚本,那么第二个人提交时会出现冲突 +如果二人同时修改了delete脚本,那么第二个人提交时会出现冲突。 ![图片](./../../../.vuepress/public/images/4PQ6luiMXmLjedor.png) -此时需要使用 git fetch拉取远程变更,然后处理冲突后再提交 +此时需要使用 git fetch拉取远程变更,然后处理冲突后再提交。 ![图片](./../../../.vuepress/public/images/3n9RTlN2vnKt9TGb.png) -修改delete脚本,提交推送到远程仓库 - -`git add`-->`git commit`-->`git push` +修改 delete 脚本,提交推送到远程仓库。(`git add` --> `git commit` --> `git push`) ![图片](./../../../.vuepress/public/images/n0cfTEGUO23Qt0xd.png) ## 私有管理团队 -一般的公司项目都是采用这种方式,开发拉取自己的分支,在上面开发功能需求,可能几个开发公用一个分支。而且关键分支一般都会设置权限。 +一般的公司项目都是采用这种方式,开发拉取自己的分支,在上面开发功能需求,可能几个开发人员共用一个分支。而且关键分支一般都会设置权限。 比如 master 分支用于发布或测试,只有管理员能够合并,开发不能推送自己的变更,只能在远程建立一个基于 master 分支的功能分支,然后拉取该功能分支到本地进行开发,开发完成后提交合并请求,管理员验证测试后通过合并请求将该功能合并到 master 分支上。 -eg:有一个项目,master分支是受保护的,只有管理员才可推送 +示例:有一个项目,master 分支是受保护的,只有管理员才可推送。 -现有两个开发,他们没有 master 分支的推送权限,所以需要新建一个分支做开发,开发完成后将该分支推送到远程 +现有两个开发,他们没有 master 分支的推送权限,所以需要新建一个分支做开发,开发完成后将该分支推送到远程。 ![图片](./../../../.vuepress/public/images/xQ7i5FVkMD9gyr3B.png) +同理,其他开发者也是建立自己的功能分支开发,然后推送到远程。 - -同理,其他开发者也是建立自己的功能分支开发,然后推送到远程 - -推送完成后,可以通过邮件或其他方式通知管理员,管理选择将分支合并到 master +推送完成后,可以通过邮件或其他方式通知管理员,管理选择将分支合并到 master。 ![图片](./../../../.vuepress/public/images/xfr53Sd0mXb7HGor.png) -然后`git push` +然后 `git push`。 ## 派生的公开项目 @@ -64,23 +59,23 @@ eg:有一个项目,master分支是受保护的,只有管理员才可推送 一般都是通过代码托管的派生功能,向一些开源项目贡献。 -eg:找到一个公开项目点击Fork +示例:找到一个公开项目点击 Fork。 ![图片](./../../../.vuepress/public/images/pbrdXYpOqWYhQtMF.png) -修改开发项目用的都是自己的派生仓库,开发完成后推送到自己的派生仓库中,这时候我们需要通知原项目的维护者,有些工作需要合并到主分支。这个行为叫做一个拉取请求(pull request) +修改开发项目用的都是自己的派生仓库,开发完成后推送到自己的派生仓库中,这时候我们需要通知原项目的维护者,有些工作需要合并到主分支。这个行为叫做一个拉取请求(Pull Request,简称 PR)。 ![图片](./../../../.vuepress/public/images/VqugQIujDzY0AEBu.png) -pull request中可以看到 自己的派生分支推送的目标分支, 代码提交记录和改动的文件内容的信息 +Pull Request 中可以看到自己的派生分支推送的目标分支,代码提交记录和改动的文件内容的信息。 ![图片](./../../../.vuepress/public/images/YXSpoCbnAtFCld8o.png) -项目维护者看到拉取请求后可以审查通过后合并 +项目维护者看到拉取请求后可以审查通过后合并。 ![图片](./../../../.vuepress/public/images/LxZH5uzWL2ADTOoX.png) -一般情况下,优秀的开源项目会有很多pull request,管理员怎么拉取有些看心情.. +一般情况下,优秀的开源项目会有很多 Pull Request,管理员怎么拉取有些看心情...... ## 通过邮件的公开项目 @@ -90,12 +85,13 @@ pull request中可以看到 自己的派生分支推送的目标分支, 代码 ![图片](./../../../.vuepress/public/images/AaAiOGzJj4Qk5H2k.png) -可以直接将这个文件放到邮箱客户端中发送,也可以在`git config`中配置SMTP服务器信息来发送 +可以直接将这个文件放到邮箱客户端中发送,也可以在 `git config` 中配置 SMTP 服务器信息来发送。 -``` +```ini smtpencryption = tls smtpserver = smtp.gmail.com smtpuser = user@gmail.com smtpserverport = 587 ``` -配置完成后使用`git send-email *.patch`命令来发送补丁 \ No newline at end of file + +配置完成后使用 `git send-email *.patch` 命令来发送补丁。 diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/3. \347\273\264\346\212\244\351\241\271\347\233\256.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/3. \347\273\264\346\212\244\351\241\271\347\233\256.md" index 9089ff807890c8d9181c0aa1e51406f0255efec3..b172b212594281a54c5073456f49335731e6cd27 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/3. \347\273\264\346\212\244\351\241\271\347\233\256.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\210\206\345\270\203\345\274\217 Git/3. \347\273\264\346\212\244\351\241\271\347\233\256.md" @@ -3,35 +3,36 @@ title: 维护项目 permalink: /git-tutorial/maintaining-projects --- - ## 应用来自邮件的补丁 -应用补丁有两种方式 git apply``git am +应用补丁有两种方式 `git apply` 和 `git am`。 -1.使用`apply`命令 +### 使用 `apply` 命令 ![图片](./../../../.vuepress/public/images/JNw7XKxRgJbwudNw.png) -`git apply`不会为你创建提交——在运行之后,需要手动暂存并提交补丁所引入的更改。 +`git apply` 不会为你创建提交 —— 在运行之后,需要手动暂存并提交补丁所引入的更改。 -在实际应用补丁前,你还可以使用`git apply`来检查补丁是否可以顺利应用——即对补丁运行`git apply --check`命令: +在实际应用补丁前,你还可以使用 `git apply` 来检查补丁是否可以顺利应用 —— 即对补丁运行 `git apply --check` 命令: ![图片](./../../../.vuepress/public/images/7EFVgJ1TEuhPhnVS.png) 如果没有产生输出,则该补丁可以顺利应用。 如果检查失败了,该命令还会以一个非零的状态退出,所以需要时你也可以在脚本中使用它。 -**2.使用**`am`命令 +### 使用 `am` 命令 -要应用一个由`format-patch`命令生成的补丁,你应该使用`git am`命令 (`am`表示它“应用(Apply)一系列来自邮箱(Mailbox)的补丁”)。 从技术的角度看,`git am`是为了读取 mbox 文件而构建的, mbox 是一种用来在单个文本文件中存储一个或多个电子邮件消息的简单纯文本格式。 其大致格式如下所示: +要应用一个由 `format-patch` 命令生成的补丁,你应该使用 `git am` 命令 (`am` 表示它“应用(Apply)一系列来自邮箱(Mailbox)的补丁”)。从技术的角度看,`git am` 是为了读取 mbox 文件而构建的,mbox 是一种用来在单个文本文件中存储一个或多个电子邮件消息的简单纯文本格式。其大致格式如下所示: ![图片](./../../../.vuepress/public/images/qzDGJTqJC6PMXp8E.png) -这其实就是`git format-patch`命令输出的开始几行, 而同时它也是有效的 mbox 电子邮件格式。 如果有人使用`git send-email`命令将补丁以电子邮件的形式发送给你, 你便可以将它下载为 mbox 格式的文件,之后将`git am`命令指向该文件,它会应用其中包含的所有补丁。 +这其实就是 `git format-patch` 命令输出的开始几行, 而同时它也是有效的 mbox 电子邮件格式。 如果有人使用 `git send-email` 命令将补丁以电子邮件的形式发送给你,你便可以将它下载为 mbox 格式的文件,之后将 `git am` 命令指向该文件,它会应用其中包含的所有补丁。 ```shell git am +补丁 ``` -`git am`命令创建了一个新的提交。 其中的作者信息来自于电子邮件头部的 From 和 Date 字段,提交消息则取自 Subject 和邮件正文中补丁之前的内容。 + +`git am` 命令创建了一个新的提交。 其中的作者信息来自于电子邮件头部的 From 和 Date 字段,提交消息则取自 Subject 和邮件正文中补丁之前的内容。 + ## 检出远程分支 ### **持续性合作** @@ -44,11 +45,12 @@ $ git fetch $ git checkout -b will_test_202008 Switched to a new branch 'will_test_202008' ``` -这种方式对于长期合作十分有用。当对方再次做了更改,因为之前已经设置好远程分支了, 我们就可以直接进行`fetch`和`checkout`操作。 + +这种方式对于长期合作十分有用。当对方再次做了更改,因为之前已经设置好远程分支了, 我们就可以直接进行 `fetch` 和 `checkout` 操作。 ### **非持续性合作** -对于非持续性的合作,如果你依然想要以这种方式拉取数据的话,你可以对远程版本库的 URL 调用`git pull`命令。 这会执行一个一次性的抓取,而不会将该 URL 存为远程引用 +对于非持续性的合作,如果你依然想要以这种方式拉取数据的话,你可以对远程版本库的 URL 调用 `git pull` 命令。 这会执行一个一次性的抓取,而不会将该 URL 存为远程引用。 ```shell $ git pull https://gitee.com/willcoder/fake-project.git @@ -60,12 +62,15 @@ Unpacking objects: 100% (25/25), done. From https://gitee.com/willcoder/fake-project * branch HEAD -> FETCH_HEAD ``` + ## 确定引入了哪些东西 ```shell $ git diff master ``` -这个命令会输出一个`diff`,但它可能并不是我们想要的。 + +这个命令会输出一个 `diff`,但它可能并不是我们想要的。 + 比如说你在 master 分支中向某个文件添加了一行内容,那么直接比对最新快照的结果看上去就像是你在主题分支中将这一行删除了。所以我们需要让 Git 对主题分支上最新的提交与该分支与 master 分支的首个公共祖先进行比较。 可以手工的方式找出公共祖先,并对其显式运行 diff 命令: @@ -75,15 +80,21 @@ $ git merge-base will_test_202008 master 24de949bb7c23ff052d5b39d01d809e86dd43fd2 $ git diff 24de94 ``` + 或者,更简洁的形式: + ```shell $ git diff $(git merge-base will_test_202008 master) ``` -然而,这种做法比较麻烦,所以 Git 提供了一种比较便捷的方式:三点语法。 对于`git diff`命令来说,你可以通过把 ... 置于另一个分支名后来对该分支的最新提交与两个分支的共同祖先进行比较: + +然而,这种做法比较麻烦,所以 Git 提供了一种比较便捷的方式:三点语法。 对于 `git diff` 命令来说,你可以通过把 `...` 置于另一个分支名后来对该分支的最新提交与两个分支的共同祖先进行比较: + ```shell $ git diff master...will_test_202008 ``` -该命令仅会显示自当前主题分支与`master`分支的共同祖先起,该分支中的工作。 这个语法很有用,应该牢记。 + +该命令仅会显示自当前主题分支与 `master` 分支的共同祖先起,该分支中的工作。 这个语法很有用,应该牢记。 + ## 将贡献的工作整合进来 ### **合并工作流** @@ -97,57 +108,71 @@ $ git diff master...will_test_202008 ```shell git cherry-pick ``` + ### **Rerere** -维护一个项目,有时需要做大量的合并或变基,所以冲突也会时有发生。Git提供`rerere`功能帮助维护者处理冲突。 -`rerere`是隐藏功能,可以通过配置打开 +维护一个项目,有时需要做大量的合并或变基,所以冲突也会时有发生。Git 提供 `rerere` 功能帮助维护者处理冲突。 + +`rerere` 是隐藏功能,可以通过以下配置打开: ```shell git config --global rerere.enabled true ``` + 它的作用是缓存第一次处理冲突的方案,在下次碰到类似的冲突时使用缓存方案自动处理。 + ## 为发布打标签 -当我们决定发布时,可以为发布打一个标签或者版本号 +当我们决定发布时,可以为发布打一个标签或者版本号: ```shell git tag -s v1.2 -m 'version 1.2 FixBugs' ``` -查看标签命令 + +查看标签命令: + ```shell git show v1.2 ``` + ## 生成一个构建号 -使用`git describe`命令。作为回应,Git 将会生成一个字符串, 它由最近的标签名、自该标签之后的提交数目和你所描述的提交的部分 SHA-1 值构成 +使用 `git describe` 命令。作为回应,Git 将会生成一个字符串, 它由最近的标签名、自该标签之后的提交数目和你所描述的提交的部分 SHA-1 值构成。 ```shell $ git describe master ``` -默认情况下,`git describe`命令需要有注解的标签(即使用`-a`或`-s`选项创建的标签); -如果没有则会报错 + +默认情况下,`git describe` 命令需要有注解的标签(即使用 `-a` 或 `-s` 选项创建的标签); + +如果没有则会报错: ```shell fatal: No annotated tags can describe '24de949bb7c23ff052d5b39d01d809e86dd43fd2'. However, there were unannotated tags: try --tags. ``` -如果想使用轻量标签(无注解的标签),请在命令后添加`--tags`选项。 你也可以使用这个字符串来调用`git checkout`或`git show`命令, 但是这依赖于其末尾的简短`SHA-1`值,因此不一定一直有效。 + +如果想使用轻量标签(无注解的标签),请在命令后添加 `--tags` 选项。 你也可以使用这个字符串来调用 `git checkout` 或 `git show` 命令,但是这依赖于其末尾的简短 `SHA-1` 值,因此不一定一直有效。 + ## 准备一次发布 -我们需要为那些不使用 Git 的包创建一个快照归档。使用`git archive`命令完成此工作 +我们需要为那些不使用 Git 的包创建一个快照归档。使用 `git archive` 命令完成此工作。 ```shell $ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz $ ls *.tar.gz ``` -类似的打一个zip格式包,需要向`git archive`命令传递`--format=zip`选项: + +类似地,打一个 zip 格式包,需要向 `git archive` 命令传递 `--format=zip` 选项: + ```shell $ git archive master --prefix='project/' --format=zip > `git describe master`.zip ``` + ## 制作提交简报 -使用`git shortlog`命令可以快速生成一份包含从上次发布之后项目新增内容的修改日志(changelog)类文档。 它会对你给定范围内的所有提交进行总结。 +使用 `git shortlog` 命令可以快速生成一份包含从上次发布之后项目新增内容的修改日志(changelog)类文档。 它会对你给定范围内的所有提交进行总结。 ```shell $ git shortlog --no-merges master @@ -159,4 +184,5 @@ will (4): testSQL insertSQL git apply -``` \ No newline at end of file +``` + diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/1. Git \351\205\215\347\275\256.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/1. Git \351\205\215\347\275\256.md" index 945f299d99ac3b14f8c4472fa6efb3243a27b204..b2c7e9ced0ede671b73b880b05822f9f9ca071de 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/1. Git \351\205\215\347\275\256.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/1. Git \351\205\215\347\275\256.md" @@ -3,27 +3,30 @@ title: Git 配置 permalink: /git-tutorial/git-config --- -配置 Git 命令`git config`。 比如设置用户名和邮件地址: +配置 Git 命令 `git config`。 比如设置用户名和邮件地址: ```shell $ git config --global user.name "will" $ git config --global user.email willcoder@qq.com ``` + 取消设置命令为 + ```shell $ git config --global --unset ``` -Git 有三个配置,第一个为系统级的`/etc/gitconfig`文件,该文件含有系统里每位用户及他们所拥有的仓库的配置值。 如果你传递`--system`选项给`git config`,它就会读写该文件。 + +Git 有三个配置,第一个为系统级的 `/etc/gitconfig` 文件,该文件含有系统里每位用户及他们所拥有的仓库的配置值。 如果你传递 `--system` 选项给 `git config`,它就会读写该文件。 ![图片](./../../../.vuepress/public/images/S0rEf4tVYaKZ3ESY.png) -接下来 Git 会查找每个用户的`~/.gitconfig`文件(或者`~/.config/git/config`文件)。 你可以传递`--global`选项让 Git 读写该文件。 +接下来 Git 会查找每个用户的 `~/.gitconfig` 文件(或者 `~/.config/git/config` 文件)。 你可以传递 `--global` 选项让 Git 读写该文件。 ![图片](./../../../.vuepress/public/images/A3FZdN0fYnEPz77a.png) -最后 Git 会查找你正在操作的仓库所对应的 Git 目录下的配置文件(`.git/config`)。 这个文件中的值只对该仓库有效,它对应于向`git config`传递`--local`选项。 +最后 Git 会查找你正在操作的仓库所对应的 Git 目录下的配置文件(`.git/config`)。 这个文件中的值只对该仓库有效,它对应于向 `git config` 传递 `--local` 选项。 -以上三个层次中每层的配置(系统、全局、本地)都会覆盖掉上一层次的配置,所以`.git/config`中的值会覆盖掉`/etc/gitconfig`中所对应的值。 +以上三个层次中每层的配置(系统、全局、本地)都会覆盖掉上一层次的配置,所以 `.git/config` 中的值会覆盖掉 `/etc/gitconfig` 中所对应的值。 ![图片](./../../../.vuepress/public/images/ZncMW7ny328GuAG0.png) @@ -34,12 +37,14 @@ Git 能够识别的配置项分为两大类:客户端和服务器端。 其中 ```shell $ man git-config ``` + 这个命令列出了所有可用的选项,以及与之相关的介绍。 你也可以在[http://git-scm.com/docs/git-config](http://git-scm.com/docs/git-config)找到同样的内容。 + ### **commit.template** 如果把此项指定为你的系统上某个文件的路径,当你提交的时候, Git 会使用该文件的内容作为提交的默认初始化信息。 创建的自定义提交模版中的值可以用来提示自己或他人适当的提交格式和风格。 -例如:考虑以下`.commitMsg.txt`模板文件: +例如:考虑以下 `.commitMsg.txt` 模板文件: ```shell Subject line (try to keep under 50 characters) @@ -47,14 +52,18 @@ Multi-line description of commit, feel free to be detailed. [Ticket: X] ``` -注意此提交模版是如何提示提交者保持主题的简短(为了精简`git log --oneline`的输出), 如何在后面添加进一步的详情,如何引用问题和 bug 跟踪系统的工单号(Ticket),如果有的话。 -要想让 Git 把它作为运行`git commit`时显示在你的编辑器中的默认信息,如下设置`commit.template`: + +注意此提交模版是如何提示提交者保持主题的简短(为了精简 `git log --oneline` 的输出), 如何在后面添加进一步的详情,如何引用问题和 bug 跟踪系统的工单号(Ticket),如果有的话。 + +要想让 Git 把它作为运行 `git commit` 时显示在你的编辑器中的默认信息,如下设置 `commit.template`: ```shell $ git config --global commit.template .commitMsg.txt $ git commit ``` + 当你提交时,编辑器中就会显示如下的提交信息占位符: + ```shell Subject line (try to keep under 50 characters)^M ^M @@ -72,29 +81,35 @@ feel free to be detailed.^M #       new file:   .commitMsg.txt # ``` + 如果你的团队对提交信息有格式要求,可以在系统上创建一个文件,并配置 Git 把它作为默认的模板,这样可以更加容易地使提交信息遵循格式。 + ### **core.pager** -该配置项指定 Git 运行诸如`log`和`diff`等命令所使用的分页器。 你可以把它设置成用`more`或者任何你喜欢的分页器(默认用的是`less`),当然也可以设置成空字符串,关闭该选项: +该配置项指定 Git 运行诸如 `log` 和 `diff` 等命令所使用的分页器。 你可以把它设置成用 `more` 或者任何你喜欢的分页器(默认用的是 `less`),当然也可以设置成空字符串,关闭该选项: ```shell $ git config --global core.pager '' ``` + 这样不管命令的输出量多少,Git 都会在一页显示所有内容。 + ### **core.excludesfile** -我们可以在项目的`.gitignore`文件里面规定无需纳入 Git 管理的文件的模板,这样它们既不会出现在未跟踪列表, 也不会在运行`git add`后被暂存。 +我们可以在项目的 `.gitignore` 文件里面规定无需纳入 Git 管理的文件的模板,这样它们既不会出现在未跟踪列表, 也不会在运行 `git add` 后被暂存。 -不过有些时候,你想要在你所有的版本库中忽略掉某一类文件。 如果你的操作系统是 macOS,很可能就是指`.DS_Store`。 如果你把 Emacs 或 Vim 作为首选的编辑器,你肯定知道以`~`结尾的文件名。 +不过有些时候,你想要在你所有的版本库中忽略掉某一类文件。 如果你的操作系统是 macOS,很可能就是指 `.DS_Store`。 如果你把 Emacs 或 Vim 作为首选的编辑器,你肯定知道以`~`结尾的文件名。 -这个配置允许你设置类似于全局生效的`.gitignore`文件。 如果你按照下面的内容创建一个`~/.gitignore_global`文件: +这个配置允许你设置类似于全局生效的 `.gitignore` 文件。 如果你按照下面的内容创建一个 `~/.gitignore_global` 文件: ```shell *~ .*.swp .DS_Store ``` -……然后运行`git config --global core.excludesfile ~/.gitignore_global`,Git 将把那些文件永远地拒之门外。 + +然后运行 `git config --global core.excludesfile ~/.gitignore_global`,Git 将把那些文件永远地拒之门外。 + ### **help.autocorrect** 假如你打错了一条命令,会显示: @@ -105,14 +120,18 @@ git:'chekcout' 不是一个 git 命令。参见 'git --help'。 您指的是这个么? checkout ``` -Git 会尝试猜测你的意图,但是它不会越俎代庖。 如果你把`help.autocorrect`设置成 1,那么只要有一个命令被模糊匹配到了,Git 会自动运行该命令。 + +Git 会尝试猜测你的意图,但是它不会越俎代庖。 如果你把 `help.autocorrect` 设置成 1,那么只要有一个命令被模糊匹配到了,Git 会自动运行该命令。 + ```shell $ git chekcout master 警告:您运行一个不存在的 Git 命令 'chekcout'。继续执行假定您要要运行的 是 'checkout' 在 0.1 秒钟后自动运行... ``` -注意提示信息中的“0.1 秒”。`help.autocorrect`接受一个代表十分之一秒的整数。 所以如果你把它设置为 50, Git 将在自动执行命令前给你 5 秒的时间改变主意。 + +注意提示信息中的“0.1 秒”。`help.autocorrect` 接受一个代表十分之一秒的整数。 所以如果你把它设置为 50, Git 将在自动执行命令前给你 5 秒的时间改变主意。 + ## Git 中的着色 Git 充分支持对终端内容着色,对你凭肉眼简单、快速分析命令输出有很大帮助。 你可以设置许多的相关选项来满足自己的偏好。 @@ -124,12 +143,14 @@ Git 会自动着色大部分输出内容,但如果你不喜欢花花绿绿, ```shell $ git config --global color.ui false ``` -这个设置的默认值是`auto`,它会着色直接输出到终端的内容;而当内容被重定向到一个管道或文件时,则忽略着色功能。 -你也可以设置成`always`,来忽略掉管道和终端的不同,即在任何情况下着色输出。 你很少会这么设置,在大多数场合下,如果你想在被重定向的输出中插入颜色码,可以传递`--color`标志给 Git 命令来强制它这么做。 默认设置就已经能满足大多数情况下的需求了。 + +这个设置的默认值是 `auto`,它会着色直接输出到终端的内容;而当内容被重定向到一个管道或文件时,则忽略着色功能。 + +你也可以设置成 `always`,来忽略掉管道和终端的不同,即在任何情况下着色输出。 你很少会这么设置,在大多数场合下,如果你想在被重定向的输出中插入颜色码,可以传递 `--color` 标志给 Git 命令来强制它这么做。 默认设置就已经能满足大多数情况下的需求了。 ### **color.*** -要想具体到哪些命令输出需要被着色以及怎样着色,你需要用到和具体命令有关的颜色配置选项。 它们都能被置为`true`、`false`或`always`: +要想具体到哪些命令输出需要被着色以及怎样着色,你需要用到和具体命令有关的颜色配置选项。 它们都能被置为 `true`、`false` 或 `always`: ```shell color.branch @@ -137,11 +158,15 @@ color.diff color.interactive color.status ``` -另外,以上每个配置项都有子选项,它们可以被用来覆盖其父设置,以达到为输出的各个部分着色的目的。 例如,为了让`diff`的输出信息以蓝色前景、黑色背景和粗体显示,你可以运行 + +另外,以上每个配置项都有子选项,它们可以被用来覆盖其父设置,以达到为输出的各个部分着色的目的。 例如,为了让 `diff` 的输出信息以蓝色前景、黑色背景和粗体显示,你可以运行: + ```shell $ git config --global color.diff.meta "blue black bold" ``` -你能设置的颜色有:`normal`、`black`、`red`、`green`、`yellow`、`blue`、`magenta`、`cyan`或`white`。 正如以上例子设置的粗体属性,想要设置字体属性的话,可以选择包括:`bold`、`dim`、`ul`(下划线)、`blink`、`reverse`(交换前景色和背景色)。 + +你能设置的颜色有:`normal`、`black`、`red`、`green`、`yellow`、`blue`、`magenta`、`cyan` 或 `white`。 正如以上例子设置的粗体属性,想要设置字体属性的话,可以选择包括:`bold`、`dim`、`ul`(下划线)、`blink`、`reverse`(交换前景色和背景色)。 + ## 格式化与多余的空白字符 格式化与多余的空白字符是许多开发人员在协作时,特别是在跨平台情况下,不时会遇到的令人头疼的琐碎的问题。 由于编辑器的不同或者文件行尾的换行符在 Windows 下被替换了,一些细微的空格变化会不经意地混入提交的补丁或其它协作成果中。 不用怕,Git 提供了一些配置项来帮助你解决这些问题。 @@ -150,86 +175,106 @@ $ git config --global color.diff.meta "blue black bold" 假如你正在 Windows 上写程序,而你的同伴用的是其他系统(或相反),你可能会遇到 CRLF 问题。 这是因为 Windows 使用回车(CR)和换行(LF)两个字符来结束一行,而 macOS 和 Linux 只使用换行(LF)一个字符。 虽然这是小问题,但它会极大地扰乱跨平台协作。许多 Windows 上的编辑器会悄悄把行尾的换行字符转换成回车和换行, 或在用户按下 Enter 键时,插入回车和换行两个字符。 -Git 可以在你提交时自动地把回车和换行转换成换行,而在检出代码时把换行转换成回车和换行。 你可以用`core.autocrlf`来打开此项功能。 如果是在 Windows 系统上,把它设置成`true`,这样在检出代码时,换行会被转换成回车和换行: +Git 可以在你提交时自动地把回车和换行转换成换行,而在检出代码时把换行转换成回车和换行。 你可以用 `core.autocrlf` 来打开此项功能。 如果是在 Windows 系统上,把它设置成 `true`,这样在检出代码时,换行会被转换成回车和换行: ```shell $ git config --global core.autocrlf true ``` -如果使用以换行作为行结束符的 Linux 或 macOS,你不需要 Git 在检出文件时进行自动的转换; 然而当一个以回车加换行作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 你可以把`core.autocrlf`设置成 input 来告诉 Git 在提交时把回车和换行转换成换行,检出时不转换: + +如果使用以换行作为行结束符的 Linux 或 macOS,你不需要 Git 在检出文件时进行自动的转换; 然而当一个以回车加换行作为行结束符的文件不小心被引入时,你肯定想让 Git 修正。 你可以把 `core.autocrlf` 设置成 input 来告诉 Git 在提交时把回车和换行转换成换行,检出时不转换: + ```shell $ git config --global core.autocrlf input ``` + 这样在 Windows 上的检出文件中会保留回车和换行,而在 macOS 和 Linux 上,以及版本库中会保留换行。 -如果你是 Windows 程序员,且正在开发仅运行在 Windows 上的项目,可以设置`false`取消此功能,把回车保留在版本库中: + +如果你是 Windows 程序员,且正在开发仅运行在 Windows 上的项目,可以设置 `false` 取消此功能,把回车保留在版本库中: ```shell $ git config --global core.autocrlf false ``` + ### **core.whitespace** + Git 预先设置了一些选项来探测和修正多余空白字符问题。 它提供了六种处理多余空白字符的主要选项 —— 其中三个默认开启,另外三个默认关闭,不过你可以自由地设置它们。 默认被打开的三个选项是:`blank-at-eol`,查找行尾的空格;`blank-at-eof`,盯住文件底部的空行;`space-before-tab`,警惕行头 tab 前面的空格。 -默认被关闭的三个选项是:`indent-with-non-tab`,揪出以空格而非 tab 开头的行(你可以用`tabwidth`选项控制它);`tab-in-indent`,监视在行头表示缩进的 tab;`cr-at-eol`,告诉 Git 忽略行尾的回车。 +默认被关闭的三个选项是:`indent-with-non-tab`,揪出以空格而非 tab 开头的行(你可以用 `tabwidth` 选项控制它);`tab-in-indent`,监视在行头表示缩进的 tab;`cr-at-eol`,告诉 Git 忽略行尾的回车。 -通过设置`core.whitespace`,你可以让 Git 按照你的意图来打开或关闭以逗号分割的选项。 要想关闭某个选项,你可以在输入设置选项时不指定它或在它前面加个`-`。 例如,如果你想要打开除`space-before-tab` 之外的所有选项,那么可以这样 (`trailing-space`涵盖了`blank-at-eol`和`blank-at-eof`): +通过设置 `core.whitespace`,你可以让 Git 按照你的意图来打开或关闭以逗号分割的选项。 要想关闭某个选项,你可以在输入设置选项时不指定它或在它前面加个 `-`。 例如,如果你想要打开除 `space-before-tab` 之外的所有选项,那么可以这样 (`trailing-space` 涵盖了 `blank-at-eol` 和 `blank-at-eof`): ```shell $ git config --global core.whitespace \ trailing-space,-space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol ``` + 你也可以只指定自定义的部分: + ```shell $ git config --global core.whitespace \ -space-before-tab,indent-with-non-tab,tab-in-indent,cr-at-eol ``` -当你运行`git diff`命令并尝试给输出着色时,Git 将探测到这些问题,因此你在提交前就能修复它们。 用`git apply`打补丁时你也会从中受益。 如果正准备应用的补丁存有特定的空白问题,你可以让 Git 在应用补丁时发出警告: + +当你运行 `git diff` 命令并尝试给输出着色时,Git 将探测到这些问题,因此你在提交前就能修复它们。 用 `git apply` 打补丁时你也会从中受益。 如果正准备应用的补丁存有特定的空白问题,你可以让 Git 在应用补丁时发出警告: + ```shell $ git apply --whitespace=warn ``` + 或者让 Git 在打上补丁前自动修正此问题: + ```shell $ git apply --whitespace=fix ``` -这些选项也能运用于`git rebase`。 如果提交了有空白问题的文件,但还没推送到上游,你可以运行`git rebase --whitespace=fix`来让 Git 在重写补丁时自动修正它们。 + +这些选项也能运用于 `git rebase`。 如果提交了有空白问题的文件,但还没推送到上游,你可以运行 `git rebase --whitespace=fix` 来让 Git 在重写补丁时自动修正它们。 + ## Git 客户端代理 一般情况下,公司的网络都可以登陆GitHub或者Gitee,但是有些公司为了网络安全,也会网络加域,开发使用内网环境。这也是为了代码安全,防止泄露。 如果此时我们在 Gitee 发现一个不错的项目,想要 clone 下来学习一下。此时会报出 time out 或者443的错误,fatal: HTTP request failed。 -这时配置代理可解决问题 +这时配置代理可解决问题。 ```shell git config --global http.proxy http://myuser:mypassword@myproxy:8080 ``` + ## 服务器端配置 Git 服务器端的配置项相对来说并不多,但仍有一些饶有生趣的选项值得你一看。 ### **receive.fsckObjects** -Git 能够确认每个对象的有效性以及 SHA-1 检验和是否保持一致。 但 Git 不会在每次推送时都这么做。这个操作很耗时间,很有可能会拖慢提交的过程,特别是当库或推送的文件很大的情况下。 如果想在每次推送时都要求 Git 检查一致性,设置`receive.fsckObjects`为 true 来强迫它这么做: +Git 能够确认每个对象的有效性以及 SHA-1 检验和是否保持一致。 但 Git 不会在每次推送时都这么做。这个操作很耗时间,很有可能会拖慢提交的过程,特别是当库或推送的文件很大的情况下。 如果想在每次推送时都要求 Git 检查一致性,设置 `receive.fsckObjects` 为 true 来强迫它这么做: ```shell $ git config --system receive.fsckObjects true ``` + 现在 Git 会在每次推送生效前检查库的完整性,确保没有被有问题的客户端引入破坏性数据。 + ### **receive.denyNonFastForwards** -如果你变基已经被推送的提交,继而再推送,又或者推送一个提交到远程分支,而这个远程分支当前指向的提交不在该提交的历史中,这样的推送会被拒绝。 这通常是个很好的策略,但有时在变基的过程中,你确信自己需要更新远程分支,可以在 push 命令后加`-f`标志来强制更新(force-update)。 +如果你变基已经被推送的提交,继而再推送,又或者推送一个提交到远程分支,而这个远程分支当前指向的提交不在该提交的历史中,这样的推送会被拒绝。 这通常是个很好的策略,但有时在变基的过程中,你确信自己需要更新远程分支,可以在 push 命令后添加 `-f` 标志来强制更新(force-update)。 -要禁用这样的强制更新推送(force-pushes),可以设置`receive.denyNonFastForwards`: +要禁用这样的强制更新推送(force-pushes),可以设置 `receive.denyNonFastForwards`: ```shell $ git config --system receive.denyNonFastForwards true ``` + 稍后我们会提到,用服务器端的接收钩子也能达到同样的目的。 那种方法可以做到更细致的控制,例如禁止某一类用户做非快进(non-fast-forwards)推送。 + ### **receive.denyDeletes** -有一些方法可以绕过`denyNonFastForwards`策略。其中一种是先删除某个分支,再连同新的引用一起推送回该分支。 把`receive.denyDeletes`设置为 true 可以把这个漏洞补上: +有一些方法可以绕过 `denyNonFastForwards` 策略。其中一种是先删除某个分支,再连同新的引用一起推送回该分支。 把 `receive.denyDeletes` 设置为 true 可以把这个漏洞补上: ```shell $ git config --system receive.denyDeletes true ``` -这样会禁止通过推送删除分支和标签 — 没有用户可以这么做。 要删除远程分支,必须从服务器手动删除引用文件。 \ No newline at end of file + +这样会禁止通过推送删除分支和标签 — 没有用户可以这么做。 要删除远程分支,必须从服务器手动删除引用文件。 diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/2. Git \345\261\236\346\200\247.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/2. Git \345\261\236\346\200\247.md" index efcc20f10295527cfa3c9f3ab8dd84d710dd6a4f..103c6808763ccf0508d97149380285efc603415f 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/2. Git \345\261\236\346\200\247.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/2. Git \345\261\236\346\200\247.md" @@ -2,18 +2,21 @@ tltle: Git 属性 permalink: /git-tutorial/git-attributes --- + ## Git 属性 Git 属性是针对特定的路径配置的设置项。通过使用属性,你可以对项目中的文件或目录单独定义不同的合并策略,让 Git 知道怎样比较非文本文件,或者让 Git 在提交或检出前过滤内容。 -Git的gitattributes文件是一个文本文件,文件中的一行定义一个路径的若干个属性。 +Git 的 gitattributes 文件是一个文本文件,文件中的一行定义一个路径的若干个属性。 -可以在`.git/info/attributes`文件中进行设置,也可以在项目根目录建立`.gitattributes`文件。配置的属性格式如下: +可以在 `.git/info/attributes` 文件中进行设置,也可以在项目根目录建立 `.gitattributes` 文件。配置的属性格式如下: ```shell 要匹配的文件模式 属性1 属性2 ... ``` + 例子:[https://www.cnblogs.com/qiqi715/p/9286468.html](https://www.cnblogs.com/qiqi715/p/9286468.html) + gitattributes文件示例: ```shell @@ -24,50 +27,64 @@ gitattributes文件示例: *.sh text eol=lf *.py eol=lf ``` + 说明: -* 第1行,对任何文件,设置text=auto,表示`文件的行尾自动转换`。如果是文本文件,则在文件入Git库时,`行尾自动转换为LF`。如果已经在入Git库中的文件的`行尾为CRLF`,则该文件在入Git库时,不再转换为LF。 -* 第2行,对于txt文件,标记为文本文件,并进行行尾规范化。 -* 第3行,对于jpg文件,标记为非文本文件,不进行任何的行尾转换。 -* 第4行,对于vcproj文件,标记为文本文件,在文件入Git库时进行规范化,即行尾为LF。但是在检出到工作目录时,行尾自动转换为CRLF。 -* 第5行,对于sh文件,标记为文本文件,在文件入Git库时进行规范化,即行尾为LF。在检出到工作目录时,行尾也不会转换为CRLF(即保持LF)。 -* 第6行,对于py文件,只针对工作目录中的文件,行尾为LF。 -在一个 Git 库中可以有多个gitattributes文件:不同gitattributes文件中,属性设置的优先级(从高到低):/myproj/info/attributes文件/myproj/my_path/.gitattributes文件/myproj/.gitattributes文件同一个gitattributes文件中,按照行的先后顺序,如果一个文件的某个属性被多次设置,则后序的设置优先 +* 第1行,对任何文件,设置 `text=auto`,表示文件的行尾自动转换。如果是文本文件,则在文件入 Git 库时,行尾自动转换为 `LF`。如果已经在入 Git 库中的文件的行尾为 `CRLF`,则该文件在入 Git 库时,不再转换为 `LF`。 +* 第2行,对于 txt 文件,标记为文本文件,并进行行尾规范化。 +* 第3行,对于 jpg 文件,标记为非文本文件,不进行任何的行尾转换。 +* 第4行,对于 vcproj 文件,标记为文本文件,在文件入 Git 库时进行规范化,即行尾为 `LF`。但是在检出到工作目录时,行尾自动转换为 `CRLF`。 +* 第5行,对于 sh 文件,标记为文本文件,在文件入 Git 库时进行规范化,即行尾为 `LF`。在检出到工作目录时,行尾也不会转换为 `CRLF`(即保持 `LF`)。 +* 第6行,对于 py 文件,只针对工作目录中的文件,行尾为 `LF`。 + +在一个 Git 库中可以有多个 gitattributes 文件,不同 gitattributes 文件中,属性设置的优先级(从高到低): + +- /myproj/info/attributes 文件 +- /myproj/my_path/.gitattributes 文件 +- /myproj/.gitattributes 文件 + +同一个 gitattributes 文件中,按照行的先后顺序,如果一个文件的某个属性被多次设置,则后序的设置优先。 ## 关键字展开 -Git 属性提供了一种方法,让我们可以编写自己的过滤器来实现文件提交或检出时的关键字替换。 一个过滤器由“clean”和“smudge”两个子过滤器组成。 在`.gitattributes`文件中,你能对特定的路径设置一个过滤器,然后设置文件检出前的处理脚本(“smudge”)和文件暂存前的处理脚本(“clean”)。 +Git 属性提供了一种方法,让我们可以编写自己的过滤器来实现文件提交或检出时的关键字替换。 一个过滤器由“clean”和“smudge”两个子过滤器组成。 在 `.gitattributes` 文件中,你能对特定的路径设置一个过滤器,然后设置文件检出前的处理脚本(“smudge”)和文件暂存前的处理脚本(“clean”)。 ### **利用命令 clean , smudge** -在(Git 源码中)实现这个特性的原始提交信息里给出了一个简单的例子:在提交前,用`indent`程序过滤所有 C 源码。 你可以在`.gitattributes`文件中对 filter 属性设置“indent”过滤器来过滤`*.c`文件 +在(Git 源码中)实现这个特性的原始提交信息里给出了一个简单的例子:在提交前,用 `indent` 程序过滤所有 C 源码。 你可以在 `.gitattributes` 文件中对 filter 属性设置“indent”过滤器来过滤 `*.c` 文件 ```shell *.c filter=indent ``` + 然后,通过以下配置,让 Git 知道“indent”过滤器在 smudge 和 clean 时分别该做什么: + ```shell $ git config --global filter.indent.clean indent $ git config --global filter.indent.smudge cat ``` -在这个例子中,当你暂存`*.c`文件时,`indent`程序会先被触发;在把它们检出回硬盘时,`cat`程序会先被触发。`cat`在这里没什么实际作用:它仅仅把输入的数据重新输出。 这样的组合可以有效地在暂存前用`indent`过滤所有的 C 源码。 + +在这个例子中,当你暂存 `*.c` 文件时,`indent` 程序会先被触发;在把它们检出回硬盘时,`cat` 程序会先被触发。`cat` 在这里没什么实际作用:它仅仅把输入的数据重新输出。这样的组合可以有效地在暂存前用 `indent` 过滤所有的 C 源码。 + ## 导出版本库 `export-ignore` -当归档的时候,可以设置 Git 不导出某些文件和目录。 如果你不想在归档中包含某个子目录或文件,但想把它们纳入项目的版本管理中,你可以在`export-ignore`属性中指定它们。 +当归档的时候,可以设置 Git 不导出某些文件和目录。 如果你不想在归档中包含某个子目录或文件,但想把它们纳入项目的版本管理中,你可以在 `export-ignore` 属性中指定它们。 -例如,假设你在`test/`子目录下有一些测试文件,不希望它们被包含在项目导出的压缩包(tarball)中。 你可以增加下面这行到 Git 属性文件中: +例如,假设你在 `test/` 子目录下有一些测试文件,不希望它们被包含在项目导出的压缩包(tarball)中。 你可以增加下面这行到 Git 属性文件中: ```shell test/ export-ignore ``` -现在,当你运行`git archive`来创建项目的压缩包时,那个目录不会被包括在归档中。 + +现在,当你运行 `git archive` 来创建项目的压缩包时,那个目录不会被包括在归档中。 + `export-subst` -在导出文件进行部署的时候,你可以将`git log`的格式化和关键字展开处理应用到标记了`export-subst`属性的部分文件。 +在导出文件进行部署的时候,你可以将 `git log` 的格式化和关键字展开处理应用到标记了 `export-subst` 属性的部分文件。 -举个例子,如果你想在项目中包含一个叫做`LAST_COMMIT`的文件, 并在运行`git archive`的时候自动向它注入最新提交的元数据,可以像这样设置`.gitattributes`和`LAST_COMMIT`该文件: +举个例子,如果你想在项目中包含一个叫做 `LAST_COMMIT` 的文件, 并在运行 `git archive` 的时候自动向它注入最新提交的元数据,可以像这样设置 `.gitattributes` 和 `LAST_COMMIT` 该文件: ```shell LAST_COMMIT export-subst @@ -75,31 +92,39 @@ $ echo 'Last commit date: $Format:%cd by %aN$' > LAST_COMMIT $ git add LAST_COMMIT .gitattributes $ git commit -am 'adding LAST_COMMIT file for archives' ``` -运行`git archive`之后,归档文件的内容会被替换成这样: + +运行 `git archive` 之后,归档文件的内容会被替换成这样: + ```shell $ git archive HEAD | tar xCf ../deployment-testing - $ cat ../deployment-testing/LAST_COMMIT Last commit date: Tue Apr 21 08:38:48 2009 -0700 by Scott Chacon ``` + ## 合并策略 通过 Git 属性,我们可以对项目中的特定文件指定不同的合并策略。这个属性应该是最常用的一种了。 它最有用的一个选项就是,告诉 Git 当特定文件发生冲突时不要尝试合并它们,而是直接使用你这边的内容。 -考虑如下场景:项目中有一个分叉的或者定制过的主题分支,你希望该分支上的更改能合并回你的主干分支,同时需要忽略其中某些文件。此时这个合并策略就能派上用场。 假设你有一个数据库设置文件`database.xml`,在两个分支中它是不同的,而你想合并另一个分支到你的分支上,又不想弄乱该数据库文件。 你可以设置属性如下: +考虑如下场景:项目中有一个分叉的或者定制过的主题分支,你希望该分支上的更改能合并回你的主干分支,同时需要忽略其中某些文件。此时这个合并策略就能派上用场。假设你有一个数据库设置文件 `database.xml`,在两个分支中它是不同的,而你想合并另一个分支到你的分支上,又不想弄乱该数据库文件。你可以设置属性如下: ```shell database.xml merge=ours ``` -然后定义一个虚拟的合并策略,叫做`ours`: + +然后定义一个虚拟的合并策略,叫做 `ours`: + ```shell $ git config --global merge.ours.driver true ``` -如果你合并了另一个分支,`database.xml`文件不会有合并冲突,相反会显示如下信息: + +如果你合并了另一个分支,`database.xml` 文件不会有合并冲突,相反会显示如下信息: + ```shell $ git merge topic Auto-merging database.xml Merge made by recursive. ``` -这里,`database.xml`保持了主干分支中的原始版本。 \ No newline at end of file + +这里,`database.xml` 保持了主干分支中的原始版本。 diff --git "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/3. Git \351\222\251\345\255\220.md" "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/3. Git \351\222\251\345\255\220.md" index 5e5d4a5cc5ea706bd29bafe76044de4d5f47a585..9868607e1f38c8ba6f1232d706f363e91e0e43d1 100644 --- "a/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/3. Git \351\222\251\345\255\220.md" +++ "b/src/git_tutorial/Git \345\233\242\351\230\237\345\215\217\344\275\234\344\270\216\347\256\241\347\220\206\357\274\210\350\277\233\351\230\266\347\257\207\357\274\211/\345\256\232\345\210\266 Git/3. Git \351\222\251\345\255\220.md" @@ -7,86 +7,76 @@ Git 钩子是在 Git 仓库中特定事件发生时自动运行的脚本。可 ## 安装一个钩子 -钩子都被存储在 Git 目录下的`hooks`子目录中。 即绝大部分项目中的`.git/hooks`。 +钩子都被存储在 Git 目录下的 `hooks` 子目录中。即绝大部分项目中的 `.git/hooks`。 ![图片](./../../../.vuepress/public/images/TaW2ZyxOSnMzO0B9.png) -当你用`git init`初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。 这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 移除后缀后就能启用。 +当你用 `git init` 初始化一个新版本库时,Git 默认会在这个目录中放置一些示例脚本。 这些脚本除了本身可以被调用外,它们还透露了被触发时所传入的参数。 移除后缀后就能启用。 -**把一个正确命名(不带扩展名)且可执行的文件放入**`.git`目录下的`hooks`子目录中,即可激活该钩子脚本。 +**把一个正确命名(不带扩展名)且可执行的文件放入** `.git` 目录下的 `hooks` 子目录中,即可激活该钩子脚本。 -### **常用的钩子** +### 常用的钩子 -`pre-commit``pre-commit`脚本在每次你运行`git commit`命令时,Git向你询问提交信息或者产生提交对象时被执行。 - -`prepare-commit-msg``prepare-commit-msg`钩子在`pre-commit`钩子在文本编辑器中生成提交信息之后被调用。这被用来方便地修改自动生成的`squash`或`merge`提交。 - -`commit-msg``commit-msg`钩子和`prepare-commit-msg`钩子很像,但它会在用户输入提交信息之后被调用。 - -`post-commit``post-commit`钩子在`commit-msg`钩子之后立即被运行 。 - -`post-checkout``post-checkout`钩子和`post-commit`钩子很像,但它在你用`git checkout`查看引用的时候被调用。 - -`pre-rebase``pre-rebase`钩子在`git rebase`发生更改之前运行 - -`pre-receive``pre-receive`钩子在有人用`git push`向仓库推送代码时被执行。 - -`update``update`钩子在`pre-receive`之后被调用,分别被每个推送上来的引用分别调用。 - -`post-receive``post-receive`钩子在成功推送后被调用,适合用于发送通知。 +- `pre-commit`、`pre-commit` 脚本在每次你运行 `git commit` 命令时,Git 向你询问提交信息或者产生提交对象时被执行。 +- `prepare-commit-msg`、`prepare-commit-msg` 钩子在 `pre-commit` 钩子在文本编辑器中生成提交信息之后被调用。这被用来方便地修改自动生成的 `squash` 或 `merge` 提交。 +- `commit-msg`、`commit-msg` 钩子和 `prepare-commit-msg` 钩子很像,但它会在用户输入提交信息之后被调用。 +- `post-commit`、`post-commit` 钩子在 `commit-msg` 钩子之后立即被运行。 +- `post-checkout`、`post-checkout` 钩子和 `post-commit` 钩子很像,但它在你用 `git checkout` 查看引用的时候被调用。 +- `pre-rebase`、`pre-rebase` 钩子在 `git rebase` 发生更改之前运行。 +- `pre-receive`、`pre-receive` 钩子在有人用 `git push` 向仓库推送代码时被执行。 +- `update`、`update` 钩子在 `pre-receive` 之后被调用,分别被每个推送上来的引用分别调用。 +- `post-receive`、`post-receive` 钩子在成功推送后被调用,适合用于发送通知。 ## 客户端钩子 -客户端钩子分为很多种。 下面把它们分为:提交工作流钩子、电子邮件工作流钩子和其它钩子。 +客户端钩子分为很多种。下面把它们分为:提交工作流钩子、电子邮件工作流钩子和其它钩子。 ### **提交工作流钩子** 前四个钩子涉及提交的过程。 -`pre-commit`钩子在键入提交信息前运行。 它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。 - -`prepare-commit-msg`钩子在启动提交信息编辑器之前,默认信息被创建之后运行。 它允许你编辑提交者所看到的默认信息。 该钩子接收一些选项:存有当前提交信息的文件的路径、提交类型和修补提交的提交的 SHA-1 校验。 - -`commit-msg`钩子接收一个参数,此参数即上文提到的,存有当前提交信息的临时文件的路径。 如果该钩子脚本以非零值退出,Git 将放弃提交,因此,可以用来在提交通过前验证项目状态或提交信息。 - -`post-commit`钩子在整个提交过程完成后运行。 它不接收任何参数,但你可以很容易地通过运行`git log -1 HEAD`来获得最后一次的提交信息。 该钩子一般用于通知之类的事情。 +- `pre-commit` 钩子在键入提交信息前运行。 它用于检查即将提交的快照,例如,检查是否有所遗漏,确保测试运行,以及核查代码。 +- `prepare-commit-msg` 钩子在启动提交信息编辑器之前,默认信息被创建之后运行。它允许你编辑提交者所看到的默认信息。该钩子接收一些选项:存有当前提交信息的文件的路径、提交类型和修补提交的提交的 SHA-1 校验。 +- `commit-msg` 钩子接收一个参数,此参数即上文提到的,存有当前提交信息的临时文件的路径。如果该钩子脚本以非零值退出,Git 将放弃提交,因此,可以用来在提交通过前验证项目状态或提交信息。 +- `post-commit` 钩子在整个提交过程完成后运行。 它不接收任何参数,但你可以很容易地通过运行 `git log -1 HEAD` 来获得最后一次的提交信息。该钩子一般用于通知之类的事情。 ### **电子邮件工作流钩子** -你可以给电子邮件工作流设置三个客户端钩子。 它们都是由`git am`命令调用的,如果你需要通过电子邮件接收由`git format-patch`产生的补丁,这些钩子也许用得上。 +你可以给电子邮件工作流设置三个客户端钩子。它们都是由 `git am` 命令调用的,如果你需要通过电子邮件接收由 `git format-patch` 产生的补丁,这些钩子也许用得上。 -第一个运行的钩子是`applypatch-msg`。 它接收单个参数:包含请求合并信息的临时文件的名字。 如果脚本返回非零值,Git 将放弃该补丁。 你可以用该脚本来确保提交信息符合格式,或直接用脚本修正格式错误。 +第一个运行的钩子是 `applypatch-msg`。它接收单个参数:包含请求合并信息的临时文件的名字。如果脚本返回非零值,Git 将放弃该补丁。你可以用该脚本来确保提交信息符合格式,或直接用脚本修正格式错误。 -下一个在`git am`运行期间被调用的是`pre-applypatch`。 有些难以理解的是,它正好运行于应用补丁**之后**,产生提交之前,所以你可以用它在提交前检查快照。 你可以用这个脚本运行测试或检查工作区。 如果有什么遗漏,或测试未能通过,脚本会以非零值退出,中断`git am`的运行,这样补丁就不会被提交。 +下一个在 `git am` 运行期间被调用的是 `pre-applypatch`。 有些难以理解的是,它正好运行于应用补丁之后,产生提交之前,所以你可以用它在提交前检查快照。你可以用这个脚本运行测试或检查工作区。如果有什么遗漏,或测试未能通过,脚本会以非零值退出,中断 `git am` 的运行,这样补丁就不会被提交。 -`post-applypatch`运行于提交产生之后,是在`git am`运行期间最后被调用的钩子。 你可以用它把结果通知给一个小组或所拉取的补丁的作者。 但你没办法用它停止打补丁的过程。 +`post-applypatch` 运行于提交产生之后,是在 `git am` 运行期间最后被调用的钩子。你可以用它把结果通知给一个小组或所拉取的补丁的作者。但你没办法用它停止打补丁的过程。 ### **其它客户端钩子** -`pre-rebase`钩子运行于变基之前,以非零值退出可以中止变基的过程。 你可以使用这个钩子来禁止对已经推送的提交变基。 +`pre-rebase` 钩子运行于变基之前,以非零值退出可以中止变基的过程。你可以使用这个钩子来禁止对已经推送的提交变基。 -`post-rewrite`钩子被那些会替换提交记录的命令调用,比如`git commit --amend`和`git rebase`(不过不包括`git filter-branch`)。 它唯一的参数是触发重写的命令名,同时从标准输入中接受一系列重写的提交记录。 这个钩子的用途很大程度上跟`post-checkout`和`post-merge`差不多。 +`post-rewrite` 钩子被那些会替换提交记录的命令调用,比如 `git commit --amend` 和 `git rebase`(不过不包括 `git filter-branch`)。它唯一的参数是触发重写的命令名,同时从标准输入中接受一系列重写的提交记录。这个钩子的用途很大程度上跟 `post-checkout` 和 `post-merge` 差不多。 -在`git checkout`成功运行后,`post-checkout`钩子会被调用。你可以根据你的项目环境用它调整你的工作目录。 其中包括放入大的二进制文件、自动生成文档或进行其他类似这样的操作。 +在 `git checkout` 成功运行后,`post-checkout` 钩子会被调用。你可以根据你的项目环境用它调整你的工作目录。其中包括放入大的二进制文件、自动生成文档或进行其他类似这样的操作。 -在`git merge`成功运行后,`post-merge`钩子会被调用。 你可以用它恢复 Git 无法跟踪的工作区数据,比如权限数据。 这个钩子也可以用来验证某些在 Git 控制之外的文件是否存在,这样你就能在工作区改变时,把这些文件复制进来。 +在 `git merge` 成功运行后,`post-merge` 钩子会被调用。 你可以用它恢复 Git 无法跟踪的工作区数据,比如权限数据。 这个钩子也可以用来验证某些在 Git 控制之外的文件是否存在,这样你就能在工作区改变时,把这些文件复制进来。 -`pre-push`钩子会在`git push`运行期间, 更新了远程引用但尚未传送对象时被调用。 它接受远程分支的名字和位置作为参数,同时从标准输入中读取一系列待更新的引用。 你可以在推送开始之前,用它验证对引用的更新操作(一个非零的退出码将终止推送过程)。 +`pre-push` 钩子会在 `git push` 运行期间,更新了远程引用但尚未传送对象时被调用。它接受远程分支的名字和位置作为参数,同时从标准输入中读取一系列待更新的引用。你可以在推送开始之前,用它验证对引用的更新操作(一个非零的退出码将终止推送过程)。 -Git 的一些日常操作在运行时,偶尔会调用`git gc --auto`进行垃圾回收。`pre-auto-gc`钩子会在垃圾回收开始之前被调用,可以用它来提醒你现在要回收垃圾了,或者依情形判断是否要中断回收。 +Git 的一些日常操作在运行时,偶尔会调用 `git gc --auto` 进行垃圾回收。`pre-auto-gc` 钩子会在垃圾回收开始之前被调用,可以用它来提醒你现在要回收垃圾了,或者依情形判断是否要中断回收。 ## 服务器端钩子 -除了客户端钩子,作为系统管理员,你还可以使用若干服务器端的钩子对项目强制执行各种类型的策略。 这些钩子脚本在推送到服务器之前和之后运行。 推送到服务器前运行的钩子可以在任何时候以非零值退出,拒绝推送并给客户端返回错误消息,还可以依你所想设置足够复杂的推送策略。 +除了客户端钩子,作为系统管理员,你还可以使用若干服务器端的钩子对项目强制执行各种类型的策略。 这些钩子脚本在推送到服务器之前和之后运行。推送到服务器前运行的钩子可以在任何时候以非零值退出,拒绝推送并给客户端返回错误消息,还可以依你所想设置足够复杂的推送策略。 `pre-receive` -处理来自客户端的推送操作时,最先被调用的脚本是`pre-receive`。 它从标准输入获取一系列被推送的引用。如果它以非零值退出,所有的推送内容都不会被接受。 你可以用这个钩子阻止对引用进行非快进(non-fast-forward)的更新,或者对该推送所修改的所有引用和文件进行访问控制。 +处理来自客户端的推送操作时,最先被调用的脚本是`pre-receive`。 它从标准输入获取一系列被推送的引用。如果它以非零值退出,所有的推送内容都不会被接受。你可以用这个钩子阻止对引用进行非快进(non-fast-forward)的更新,或者对该推送所修改的所有引用和文件进行访问控制。 `update` -`update`脚本和`pre-receive`脚本十分类似,不同之处在于它会为每一个准备更新的分支各运行一次。 假如推送者同时向多个分支推送内容,`pre-receive`只运行一次,相比之下`update`则会为每一个被推送的分支各运行一次。 它不会从标准输入读取内容,而是接受三个参数:引用的名字(分支),推送前的引用指向的内容的 SHA-1 值,以及用户准备推送的内容的 SHA-1 值。 如果 update 脚本以非零值退出,只有相应的那一个引用会被拒绝;其余的依然会被更新。 +`update` 脚本和 `pre-receive` 脚本十分类似,不同之处在于它会为每一个准备更新的分支各运行一次。假如推送者同时向多个分支推送内容,`pre-receive` 只运行一次,相比之下 `update` 则会为每一个被推送的分支各运行一次。它不会从标准输入读取内容,而是接受三个参数:引用的名字(分支),推送前的引用指向的内容的 SHA-1 值,以及用户准备推送的内容的 SHA-1 值。 如果 update 脚本以非零值退出,只有相应的那一个引用会被拒绝;其余的依然会被更新。 `post-receive` -`post-receive`挂钩在整个过程完结以后运行,可以用来更新其他系统服务或者通知用户。 它接受与`pre-receive`相同的标准输入数据。 它的用途包括给某个邮件列表发信,通知持续集成(continous integration)的服务器, 或者更新问题追踪系统(ticket-tracking system) —— 甚至可以通过分析提交信息来决定某个问题(ticket)是否应该被开启,修改或者关闭。 该脚本无法终止推送进程,不过客户端在它结束运行之前将保持连接状态, 所以如果你想做其他操作需谨慎使用它,因为它将耗费你很长的一段时间。 +`post-receive` 挂钩在整个过程完结以后运行,可以用来更新其他系统服务或者通知用户。它接受与 `pre-receive` 相同的标准输入数据。它的用途包括给某个邮件列表发信,通知持续集成(continous integration)的服务器, 或者更新问题追踪系统(ticket-tracking system) —— 甚至可以通过分析提交信息来决定某个问题(ticket)是否应该被开启,修改或者关闭。 该脚本无法终止推送进程,不过客户端在它结束运行之前将保持连接状态, 所以如果你想做其他操作需谨慎使用它,因为它将耗费你很长的一段时间。 + diff --git a/src/git_tutorial/README.md b/src/git_tutorial/README.md index 8f6bdc63b79a315f51cb86394c791d461d5e8736..532b4e80ccdeef0d4a0f82c7e6718da82324b7fd 100644 --- a/src/git_tutorial/README.md +++ b/src/git_tutorial/README.md @@ -28,8 +28,11 @@ footer: Git 教程采用 CC-BY-SA-4.0 进行许可 | 感谢每一位参与的开 --- ### 🎩 编写人员 + @小熊 @willcoder -@Gitees Urgroßvater \ No newline at end of file +@Gitees Urgroßvater + +@阿基米东 diff --git a/src/story/readme.md b/src/story/readme.md index 619a8a3cb9f08110cf8f281c77d8241d688b1e96..6afcaea64d7ac70e9f01fbf22fa206cae81760b9 100644 --- a/src/story/readme.md +++ b/src/story/readme.md @@ -32,9 +32,9 @@ features: details: By 西狩 link: /story/stories/“我的一剂良药”之开源指北/ - - title: 要懂得舍得的UMS与JPA的故事 + - title: 要懂得舍得的UMS与JAP的故事 details: By 要懂得舍得 - link: /story/stories/要懂得舍得的UMS与JPA的故事/ + link: /story/stories/要懂得舍得的UMS与JAP的故事/ - title: 开源有魔力-DolphinScheduler和我的开源历程 details: By 鲍亮 @@ -64,21 +64,31 @@ footer: 开源指北-开源故事 采用 CC-BY-SA-4.0 进行许可 | 感谢每 ## 你也想分享你的开源故事? ### 投稿要求 + 1. 你投稿的故事内需包含以下内容: -- 如何接触/了解到这个开源项目 -- 为什么决定参与贡献 -- 参与后的收获或提升(技术上或者生活上) -- 除以上内容之外,也欢迎为开源小白写上一句鼓励的话语(可选填,非必要内容) + + - 如何接触/了解到这个开源项目; + + - 为什么决定参与贡献; + + - 参与后的收获或提升(技术上或者生活上); + + - 除以上内容之外,也欢迎为开源小白写上一句鼓励的话语(可选填,非必要内容)。 2. 投稿方式: -- 快捷入口>>[点我投稿故事](https://gitee.com/gitee-community/opensource-guide/new/master/%E5%BC%80%E6%BA%90%E6%95%85%E4%BA%8B) - + - 快捷入口 >> [点我投稿故事](https://gitee.com/gitee-community/opensource-guide/new/master/%E5%BC%80%E6%BA%90%E6%95%85%E4%BA%8B) + 3. 注意 -- 标题格式:ID |项目-参与贡献的项目名.md,例如:子知鱼否|项目-开源指北.md -- 故事字数:不少于200 字 -- 广告、灌水文章不予收录 -- 开源指北 & Gitee 具有故事宣传、使用权 + + - 标题格式:`ID |项目-参与贡献的项目名.md`,例如:`子知鱼否|项目-开源指北.md`。 + + - 故事字数:不少于200 字。 + + - 广告、灌水文章不予收录。 + + - 开源指北 & Gitee 具有故事宣传、使用权。 ### 参与奖励 -1. 故事被收录(合并PR)后,你将获得 Gitee 马克杯一个 -2. 所有被收录的故事将会同步至本页面内,更有机会获得 Gitee x OSCHINA 官方微博、微信公众号等渠道推荐,让更多人可以看到你的故事。 \ No newline at end of file +1. 故事被收录(合并 PR)后,你将获得 Gitee 马克杯一个。 +2. 所有被收录的故事将会同步至本页面内,更有机会获得 Gitee x OSCHINA 官方微博、微信公众号等渠道推荐,让更多人可以看到你的故事。 + diff --git "a/src/story/stories/DolphinScheduler\345\246\202\344\275\225\345\270\246\351\242\206\346\210\221\350\265\260\350\277\233\345\274\200\346\272\220\347\232\204\344\270\226\347\225\214.md" "b/src/story/stories/DolphinScheduler\345\246\202\344\275\225\345\270\246\351\242\206\346\210\221\350\265\260\350\277\233\345\274\200\346\272\220\347\232\204\344\270\226\347\225\214.md" index b4196bee1855098edb428327e8f9697e5f819a8e..6a22a3b9d09a30947bdc857866695a763ccc7aa9 100644 --- "a/src/story/stories/DolphinScheduler\345\246\202\344\275\225\345\270\246\351\242\206\346\210\221\350\265\260\350\277\233\345\274\200\346\272\220\347\232\204\344\270\226\347\225\214.md" +++ "b/src/story/stories/DolphinScheduler\345\246\202\344\275\225\345\270\246\351\242\206\346\210\221\350\265\260\350\277\233\345\274\200\346\272\220\347\232\204\344\270\226\347\225\214.md" @@ -1,45 +1,48 @@ ---- -title: DolphinScheduler如何带领我走进开源的世界 -author: chenxingchun -date: 2021-01-21 -permalink: /story/chenxingchun ---- - -## 摘要 - -Apache DolphinScheduler 目前是 Apache 孵化项目,目前正在快速发展中。加入Apache DolphinScheduler社区已一年多,已有 400+ 公司在生产上使用,代码+文档贡献者近200位,社区用户4000 +人。本篇文章主要介绍我在Apache DolphinScheduler的经历及收获。 - -## 个人简介 - -陈兴春,易观数科大数据平台测试工程师,Apache DolphinScheduler的一名 Commiter,拥有5年测试经验,平常主要负责千帆产品和DS的测试工作,喜欢专研新技术,对未知事物充满好奇心的一枚萌妹子。 - - -## Apache DolphinScheduler 简述 - -Apache DolphinScheduler 是一个开源的分布式去中心化、易扩展的可视化DAG大数据调度系统。 于2017年在易观数科立项,2019年3月开源,于2019年8月29日通过Apache基金会投票正式成为Apache孵化器项目。 - -Apache DolphinScheduler致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用。可调度Shell、Python、SQL、数据存储、Spark、Flink、MR、HTTP、子流程、依赖、条件判断等任务,DAG可视化,支持自定义时间调度、历史数据补数、指定单个任务运行、任务/资源监控、重跑、停止、暂停、失败重试、恢复失败、恢复运行、告警、容错、全局参数、自定义参数、系统内置参数等功能。 - - -## 结缘Apache DolphinScheduler - -2019年9月,我非常荣幸的加入易观数科,同时也加入了Apache DolphinScheduler社区,开始了与DolphinScheduler的成长之旅。DolphinScheduler是我参加的第一个开源项目,也正是Apache DolphinScheduler社区,让我知道中国开源正在崛起,中国开源的力量在壮大,越来越多的开发者及公司正在积极的拥抱开源。 - -## 入选commiter之路 - -初入DolphinScheduler社区时,@dailidong 冬哥说了一句让我至今也印象深刻的话:兴春,争取早日成为commiter。当时的我是不相信自己能成为commiter的,因为我不是开发,感觉没机会提交pr,何谈成为commiter。但是后面了解到成为commiter,不仅只有提交pr一条道路,只要为社区贡献一份力量,问题答疑、贡献文章、文档、社区运营宣传,都有机会成为commiter。 - -前期在@qiaozhanwei 占卫(DolphinScheduler PPMC)的帮助下,细心的帮我讲解DolphinScheduler业务、架构、部署以及各个服务之间的实现与联系,加上自己对linux、shell脚本、python、数据库及代码部署等有较好的基础,因此在短时间内就熟练的掌握DolphinScheduler并开始接管测试工作,把控DolphinScheduler每次发版质量的最后一道关卡。平时除了测试DolphinScheduler的业务,开始在社区进行答疑,处理GitHub上的issue,修改官网的文档。在测试V1.1.0到V1.2.0升级脚本时,发现install.sh中数据库类型为postgresql时,数据库连接却用的mysql,因此我的第一个pr产生了,哪怕只是改了一个简单的mysql,却是一个里程碑的开始,因为无数的pr及勇气都是第一个pr奠定的基石。后期经过不断的贡献与坚持,终于赶上第二批commiter的选拔,并成功入选成为DolphinScheduler的commiter。 - -当然,成为commiter不应该是加入开源项目的终极目标。成为commiter,拥有更大的操作权限,能更方便、更快捷的服务社区,同时对于项目及社区的发展与壮大,更多了一份责任,只有项目变强且被更多人及公司认可时,commiter的头衔才会变得更有意义。 - -## 社区氛围 - -社区最近多次在线上讨论master重构,经过几次会议后,加入讨论的社区人员越来越多,大家各抒己见,讨论技术实现的利与弊。作为一个测试人员,也许我不能提出专业的技术建议,也许整场会议我没有发言,但是我从不会缺席。在技术讨论过程中,我会关注开发的实现方式和逻辑,在后期测试的时候,我才能发现更多隐藏的测试点以及容易忽视的细节。 - -在DolphinScheduler社区,认识了很多大神,每天都在进行大脑风暴,讨论技术、架构及需求实现。他们利用自己休闲娱乐的时间,不断的为DolphinScheduler出谋划策,完善DolphinScheduler的功能,解决github上的issue。在他们身上,总能学到很多东西,不仅是在技术层面,更重要的是那份为了开源项目无私奉献的精神。也正是大家的贡献以及社区小伙伴的认可,社区用户群从当初的1个群增加到8个群,外加2个开发群,而且还在不断扩大,代码Contributors也从当初的1个人增长到148个,文档贡献者也有近50人了。还有一件非常值得庆贺的事情,Apache DolphinScheduler 2020年在数百个开源项目评选中脱颖而出荣获十大开源新锐项目。 - - -## 未来期许 - -Apache DolphinScheduler正在拙壮成长,希望早日毕业成为顶级项目,而且我也坚信通过社区的力量与努力,DolphinScheduler一定会开辟出自己的一片天地,被越来越多的人熟知及应用。也希望广大同胞们的日子就如DolphinScheduler的slogan一样“调度选得好、下班回家早、调度选得对、回家安心睡”。同时,DolphinScheduler也欢迎更多的小伙伴加入社区,加入开源的队伍,为开源贡献一份力所能及的力量 \ No newline at end of file +--- +title: DolphinScheduler 如何带领我走进开源的世界 +author: chenxingchun +date: 2021-01-21 +permalink: /story/chenxingchun +--- + +## 摘要 + +Apache DolphinScheduler 目前是 Apache 孵化项目,目前正在快速发展中。加入 Apache DolphinScheduler 社区已一年多,已有 400+ 公司在生产上使用,代码+文档贡献者近 200 位,社区用户4000 多人。本篇文章主要介绍我在 Apache DolphinScheduler 的经历及收获。 + +## 个人简介 + +陈兴春,易观数科大数据平台测试工程师,Apache DolphinScheduler 的一名 Commiter,拥有5年测试经验,平常主要负责千帆产品和 DS 的测试工作,喜欢专研新技术,对未知事物充满好奇心的一枚萌妹子。 + + +## Apache DolphinScheduler 简述 + +Apache DolphinScheduler 是一个开源的分布式去中心化、易扩展的可视化 DAG 大数据调度系统。于2017年在易观数科立项,2019年3月开源,于2019年8月29日通过 Apache 基金会投票正式成为 Apache 孵化器项目。 + +Apache DolphinScheduler 致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用。可调度 Shell、Python、SQL、数据存储、Spark、Flink、MR、HTTP、子流程、依赖、条件判断等任务,DAG 可视化,支持自定义时间调度、历史数据补数、指定单个任务运行、任务/资源监控、重跑、停止、暂停、失败重试、恢复失败、恢复运行、告警、容错、全局参数、自定义参数、系统内置参数等功能。 + + +## 结缘 Apache DolphinScheduler + +2019年9月,我非常荣幸的加入易观数科,同时也加入了 Apache DolphinScheduler 社区,开始了与 DolphinScheduler 的成长之旅。DolphinScheduler 是我参加的第一个开源项目,也正是 Apache DolphinScheduler 社区,让我知道中国开源正在崛起,中国开源的力量在壮大,越来越多的开发者及公司正在积极的拥抱开源。 + +## 入选 commiter 之路 + +初入 DolphinScheduler 社区时,@dailidong 冬哥说了一句让我至今也印象深刻的话:兴春,争取早日成为 commiter。当时的我是不相信自己能成为 commiter 的,因为我不是开发,感觉没机会提交 pr,何谈成为 commiter。但是后面了解到成为 commiter,不仅只有提交 pr 一条道路,只要为社区贡献一份力量,问题答疑、贡献文章、文档、社区运营宣传,都有机会成为 commiter。 + +前期在 @qiaozhanwei 占卫(DolphinScheduler PPMC)的帮助下,细心的帮我讲解 DolphinScheduler 业务、架构、部署以及各个服务之间的实现与联系,加上自己对 Linux、Shell 脚本、Python、数据库及代码部署等有较好的基础,因此在短时间内就熟练的掌握 DolphinScheduler 并开始接管测试工作,把控 DolphinScheduler 每次发版质量的最后一道关卡。平时除了测试 DolphinScheduler 的业务,开始在社区进行答疑,处理 GitHub上的 issue,修改官网的文档。在测试 V1.1.0 到 V1.2.0 升级脚本时,发现 install.sh 中数据库类型为 postgresql 时,数据库连接却用的 mysql,因此我的第一个 pr 产生了,哪怕只是改了一个简单的 mysql,却是一个里程碑的开始,因为无数的 pr 及勇气都是第一个 pr 奠定的基石。后期经过不断的贡献与坚持,终于赶上第二批 commiter 的选拔,并成功入选成为 DolphinScheduler 的 commiter。 + +当然,成为 commiter 不应该是加入开源项目的终极目标。成为 commiter,拥有更大的操作权限,能更方便、更快捷的服务社区,同时对于项目及社区的发展与壮大,更多了一份责任,只有项目变强且被更多人及公司认可时,commiter 的头衔才会变得更有意义。 + +## 社区氛围 + +社区最近多次在线上讨论 master 重构,经过几次会议后,加入讨论的社区人员越来越多,大家各抒己见,讨论技术实现的利与弊。作为一个测试人员,也许我不能提出专业的技术建议,也许整场会议我没有发言,但是我从不会缺席。在技术讨论过程中,我会关注开发的实现方式和逻辑,在后期测试的时候,我才能发现更多隐藏的测试点以及容易忽视的细节。 + +在 DolphinScheduler 社区,认识了很多大神,每天都在进行大脑风暴,讨论技术、架构及需求实现。他们利用自己休闲娱乐的时间,不断的为 DolphinScheduler 出谋划策,完善 DolphinScheduler 的功能,解决 GitHub 上的 issue。在他们身上,总能学到很多东西,不仅是在技术层面,更重要的是那份为了开源项目无私奉献的精神。也正是大家的贡献以及社区小伙伴的认可,社区用户群从当初的1个群增加到 8 个群,外加 2 个开发群,而且还在不断扩大,代码 Contributors 也从当初的 1 个人增长到 148个,文档贡献者也有近 50 人了。还有一件非常值得庆贺的事情,Apache DolphinScheduler 2020年在数百个开源项目评选中脱颖而出荣获十大开源新锐项目。 + + +## 未来期许 + +Apache DolphinScheduler 正在拙壮成长,希望早日毕业成为顶级项目,而且我也坚信通过社区的力量与努力,DolphinScheduler 一定会开辟出自己的一片天地,被越来越多的人熟知及应用。也希望广大同胞们的日子就如DolphinScheduler 的 slogan 一样“调度选得好、下班回家早、调度选得对、回家安心睡”。 + +同时,DolphinScheduler 也欢迎更多的小伙伴加入社区,加入开源的队伍,为开源贡献一份力所能及的力量! + diff --git a/src/story/stories/README.md b/src/story/stories/README.md index 08d8baf7b53c2de14e7211a99c7bf68a4ed992e8..831e4b3e6136d9106b08e327f0a60cd001134b42 100644 --- a/src/story/stories/README.md +++ b/src/story/stories/README.md @@ -1,22 +1,36 @@ -开源指北 1.0 即将上线,为了让更多开发者、开源小白更好的了解如何参与开源,欢迎有亲身参与过优秀开源项目的贡献者们在此分享自己的开源经验/故事 +开源指北 1.0 即将上线,为了让更多开发者、开源小白更好的了解如何参与开源,欢迎有亲身参与过优秀开源项目的贡献者们在此分享自己的开源经验/故事。 + +### 投稿要求 -#### 投稿要求 1. 你投稿的故事内需包含以下内容: -- 如何接触/了解到这个开源项目 -- 为什么决定参与贡献 -- 参与后的收获或提升(技术上或者生活上) -- 除以上内容之外,也欢迎为开源小白写上一句鼓励的话语(可选填,非必要内容) + + - 如何接触/了解到这个开源项目; + + - 为什么决定参与贡献; + + - 参与后的收获或提升(技术上或者生活上); + + - 除以上内容之外,也欢迎为开源小白写上一句鼓励的话语(可选填,非必要内容)。 + 2. 投稿方式: -- 快捷入口>>[点我投稿故事](https://gitee.com/gitee-community/opensource-guide/new/master/%E5%BC%80%E6%BA%90%E6%95%85%E4%BA%8B) - + - 快捷入口 >> [点我投稿故事](https://gitee.com/gitee-community/opensource-guide/new/master/%E5%BC%80%E6%BA%90%E6%95%85%E4%BA%8B) + 3. 注意 -- 标题需包含项目名,后缀为“.md ”,例如:子知鱼否与[开源/开源项目名]的故事.md -- 故事字数:不少于200 字 -- 广告、灌水文章不予收录 -- 开源指北 & Gitee 具有故事宣传、使用权 - -#### 参与奖励 -1. 故事被收录(合并PR)后,你将获得 Gitee 马克杯一份 -![输入图片说明](https://images.gitee.com/uploads/images/2021/0115/145253_2c255404_1899542.png "陶瓷杯.png") -2. 所有被收录的故事将会同步至即将上线的「开源指北」Pages 内,更有机会获得 Gitee x OSCHINA 官方微博、微信公众号等渠道推荐,让更多人可以看到你的故事。 \ No newline at end of file + + - 标题需包含项目名,后缀为“.md ”,例如:`子知鱼否与[开源/开源项目名]的故事.md`。 + + - 故事字数:不少于200 字。 + + - 广告、灌水文章不予收录。 + + - 开源指北 & Gitee 具有故事宣传、使用权。 + +### 参与奖励 + +1. 故事被收录(合并 PR)后,你将获得 Gitee 马克杯一份。 + + ![输入图片说明](./images/145253_2c255404_1899542.png "陶瓷杯.png") + +2. 所有被收录的故事将会同步至即将上线的「开源指北」Pages 内,更有机会获得 Gitee x OSCHINA 官方微博、微信公众号等渠道推荐,让更多人可以看到你的故事。 + diff --git "a/src/story/stories/\342\200\234\346\210\221\347\232\204\344\270\200\345\211\202\350\211\257\350\215\257\342\200\235\344\271\213\345\274\200\346\272\220\346\214\207\345\214\227.md" "b/src/story/stories/\342\200\234\346\210\221\347\232\204\344\270\200\345\211\202\350\211\257\350\215\257\342\200\235\344\271\213\345\274\200\346\272\220\346\214\207\345\214\227.md" index 1277f882df605dea6364ca60d00d235a0e054196..22750cb32fa3a6cf2c679cd0630e0410dacb5b81 100644 --- "a/src/story/stories/\342\200\234\346\210\221\347\232\204\344\270\200\345\211\202\350\211\257\350\215\257\342\200\235\344\271\213\345\274\200\346\272\220\346\214\207\345\214\227.md" +++ "b/src/story/stories/\342\200\234\346\210\221\347\232\204\344\270\200\345\211\202\350\211\257\350\215\257\342\200\235\344\271\213\345\274\200\346\272\220\346\214\207\345\214\227.md" @@ -1,87 +1,87 @@ ---- -title: “我的一剂良药”之开源指北 -author: 西狩 -date: 2021-01-22 -permalink: /story/ouuan ---- - -## 开篇 - -开源指北是 Gitee 开源社区送给所有开源人的一份保姆级开源百科,它的出现让开源相关知识不再像“沧海遗珠”一样散落在瀚海苍茫,让初识开源者可以从容地面对开源之海的首次“起航”,让众多热衷开源的开源爱好者在这里畅谈其所想。 - -不得不说,开源指北项目的发起是一个非常有趣的想法,其秉持着“开源问题由开源来解决”的思想,吸引了众多开源爱好者参与到这项开源运动中来,我也是其中一员。这是我参与的第一个开源项目,在拟定标题时再三思忖,结合自身的亲身感受,最终定了这个标题。至于为什么说对我而言是“一剂良药”,在下文中我会作出解释。 - -相比“满满的正能量”,我更希望从平常视角坦诚相待,有喜悦,有悲伤,有勇往直前,有踟蹰迷茫。不管读到这篇文章的你正拥有着哪种情绪,都能从这些稀松平常的小事中有所得,然后继续努力前行,成为更好的自己。 - -接下来,分享一段普普通通、简简单单的故事。 - -## 源起 - -**“青山若无素,偃蹇不相亲。要识庐山面,他年是故人。”** - -我叫西狩,有些朋友也会叫我老江,从事 Java 开发相关工作。 - -2020年是动荡的一年。从我的大脑里进行热词分析,浮现出来了很多“动荡”的词汇。比如:“疫情”、“大选”、“制裁”、“猝死”、“内卷”等等。我们深知处在一个贩卖焦虑的时代,但有时还是会不自觉地被这些外界的焦虑所影响,对于处在人生各种分岔路口的人们而言,受到的影响可能会更大。随着时间越走越快,看到很多新鲜的事物如雨后春笋般破土而出,陌生而又新奇。就像是面对琳琅满目的商品一样,一不小心便挑花了眼。这时我们可能会迷茫,但我们深知,自己需要去做些什么来面对它们。 - -我不确定每个人是否都有过这种迷茫的经历,但就我个人而言,迷茫期是经常的,也是正常的。生活是一座围城,选择了漂泊但又渴望稳定,选择了努力但又渴望闲适。“有的人想得多却做得少”,我不确定这句话是否符合自己,但我深知自己做得还远远不够。大家应该都听过这样一句话:“学习最好的时间是十年前,其次是现在”。所以,**不要害怕迷茫,只要敢于面对迷茫并踏出下一步,那就是有意义的。** - -我不确定命运是否会眷顾内心和自己拧巴的人,但能够参与一项有意义的开源活动,我觉得自己是幸运的。一切的源头是从日常阅读公众号文章开始讲起,几个月前 [张乘辉](https://github.com/objcoding) 老师的一篇推文《使用 Hexo + Gitee 快速搭建属于自己的博客》,文章内容很简单易懂,而后我开始考虑搭建自己的博客。在搭建过程中,我 Gitee 平台上无意间看到了开源指北的开源活动,怀着一颗好奇心的自己就这样与开源指北相遇了。说实话,虽然平时也会在 Github、Gitee 上转一转,但顶多都是走马观花似的了解,并没有参与到什么开源项目中。起初自己也是随便了解一下。在了解项目简介、阅读其中几篇文章后,感觉自己对一些内容有一定的认知和共鸣,而且内容还有很多缺失,于是便尝试提交了一次 PR。 - -故事讲到这里,我可能还并不会深陷其中。在提交后的第二天,官方小伙伴 [tenngo](https://gitee.com/tenngoxars) 就合并了我的 PR。及时的正向反馈让我受到了很大的鼓舞,就像是可治百病的“一剂良药”,使我无处安放的心静了下来。于是便开始了我的第一次开源之旅。 - -## 指天说地 - -**“一点浩然气,千里快哉风。”** - -在开源指北之前,其实网络上有很多开源知识的相关文章,但太过零散,不成体系,对于想要参与开源的人并不友好。开源指北最大的意义就是对开源知识的整合,它涵盖了大部分常见的入门知识,可以帮助很多想要参与开源而不知如何入手的小伙伴,所以,我想有必要分享一下在开源指北参与过程中的感受与收获。 - -在《降临》中,有句台词让我记忆深刻:“If you immerse yourself into a foreign language, you can actually rewire your brain”。正如前文提到的迷茫期,最近一年的时间里发生了很多事情,思绪万千但却发现脚步却慢了下来。当我下意识提起自己的脚步时,却感觉似乎前方全是岔路,就在这时,开源指北出现了。在参与过程中,无论是查阅资料,还是编写文章,又或是提交 PR,都能感受到开源带给自己的活力。仔细想想,当自己毕业时,不愿在一眼望到头的生活里度过一生,那么自己对未来的迷茫和担忧就可以很好地接收了,因为这就是自己想要的生活。人生在世,不如意事常八九,大多数人都并非是一帆风顺的。**与其每日杞人忧天,不如沉下心来倾听内心的想法,然后坚定地踏出接下来的每一步。** - -在开始分享开源过程中的感悟前,先谈及了心态,是因为自己深知心态对我的重要性。在自己心静下来后,做事情的效率会有明显的提高,并且在交流、沟通以及决策上都可以更加清醒。接下来,便带着这份心态聊到哪算哪喽! - -开源与我的本职专业有着密切的联系,虽然是第一次参与开源,但自己对开源并不算陌生。曾经怀着激动的心情参加的每次 Pivotal 技术峰会、各种技术的 Meetup 以及各位大佬的技术分享,在这一刻似乎派上了一定的用场。这也说明了**平日积累的重要性**,碎片化学习虽然并不能建立起心中的一套完整的框架体系,但对自己的影响是潜移默化的。我会对每个章节进行阅读,文章结构不顺就梳理结构,上下文衔接问题就修改上下文,明显出现内容缺失就通过查阅资料再加上自己的理解进行补充。后面又进行了反复的阅读,以及关注小伙伴们提交的 PR。我们会为项目中提及的“半开源”的概念展开探讨,会对开源知识互相交流以至于忘记时间,诸如 arch、CLA、中国第一个被 OSI 认可的协议等等。我们也会因为项目中的不足而争辩,而且可能最终谁也说服不了谁,大家的思想是平等的,没有对错,而最终的结论也是有趣而一致的。那么这个结论是什么呢?其实很简单,各自提交 PR 就好了。**求同存异是开源社区的不二法则,我不认可你的观点,但我尊重你表达思想的权利。** - -因工作需要,我在 2017 年加入了 Kettle 技术交流群,经过学习掌握了它,但由于后续没有机会再使用,我对 Kettle 的熟练程度大幅度下降,更不要说现在最新的开源版本。同样的原因,我在 2019 年初加入了 Skywalking 交流群,基本属于一个“潜水者”,只是经常会查看技术交流的消息。其他社群我就不一一列举了,我之所以提到这两段经历,是想反思一下自己:为什么曾经有那么多优秀的开源项目摆在自己面前,到现在自己还是一个开源小白?我感觉有两个重要的事情自己没有做得很好:**坚持和思维模式**。 - -- 参与开源不是一蹴而就的事情,我们需要花费大量的时间来将其打造成为一个更好的东西。我因为不再使用而放弃对 Kettle 的关注,所以它自然而然就离我远去了。**其实大多数人都并非天才,能成为一个项目中优秀开源者的主要原因就是坚持。** -- 我学习 Kettle 只想使用它来解决问题,但从未想过自己还可以改变它。如果保持这样的思维模式继续下去,那么坚持的意义就是十分有限的了,因为我只是一个熟练工,可能永远都无法突破成为建筑师。**一个目标是否能够可达,有时候需要的只是一个思维的转变。** - -最近看了吴晟老师在开放原子基金会 2020 年技术峰会上发表的演讲——[开源运营治理分论坛 - Educate Community Over Support Community](https://www.bilibili.com/video/BV125411E7GK?p=1&share_medium=iphone&share_plat=ios&share_source=QQ&share_tag=s_i×tamp=1611211180&unique_k=ZKplUv)。演讲中很清晰地为大家讲解了我们在开源中应该关注的重点,解释了社区各种角色的职责,也谈及了对社区发展和社区生态的看法。当然,其中让人受益匪浅的内容还有很多,而且没有太多难理解的技术,更多的是对开源经验的分享,感兴趣的小伙伴可以了解一下。这也是我的一个小建议:**多去与他人交谈,倾听他人的想法,我们需要在思想碰撞的过程中不断刺激自己进行思维升级。** - -再分享一则个人觉得有趣的事情,每个开源项目都有自己的排版规则,在参与开源指北过程中,我在一个关于排版的开源项目中发现了一个有趣的协议:WTFPL。参考知乎问答“[什么是 WTFPL(Do What the Fuck You Want to Public License),为什么会有人使用这一授权许可?](https://www.zhihu.com/question/20865060/answer/51757033)”中的描述来了解一下: - -> 由于程序拥有所有权,所以每段代码允许大家在何种程度上自然使用就成为了一个严肃的法律问题,所以就诞生了licence这个概念。其中有一些代码是写出来让大家随意免费使用的,所以licence就要规定你可以干一切事情。可是在法律里,“允许你干任何事情”这句话并不严谨,所以随着不断的诉讼、打官司、法学家的诠释,诞生了诸如 [@IAMSK](http://www.zhihu.com/people/c55d6c118b9141f20776588b0308e586) 所说的一大堆授权协议。 -> 但是问题来了。 -> 这个协议是给程序员看的,却是由法学家和律师写的。 -> 于是随着时间的推移,这些协议变得unreadable,也就是程序员根本不可能看懂。 -> -> 而这些协议还会越来越长,随着欧美法律不断地被新的判例充实。。。。 -> -> 于是一些程序员为了反抗这一恶性循环,发明了WTFPL。 -> -> 简而言之,就是:**“你TM爱干啥干啥”** - -有趣的点在于,我仿佛能脑补出当时程序员看到冗长的法律条文和专业名词的时候抓狂的面部表情,是个很有意思的小故事。 - -最后要说一下,个人认为,开源指北项目参与门槛并不高,虽然在内容上会尽力做到精益求精,但它的受众是每一个开源人,大家都可以在这里各抒己见。这个项目的维护也会一直开放,也希望能够在以后听到更多开源故事和开源声音。**毕竟开源这件事儿,一起热闹起来才好玩嘛!** - -## 北窗之友 - -**“今日北窗下,自问何所为,欣然得三友,三友者为谁?琴罢辄举酒,酒罢辄吟诗。”** - -如果说有人问:“一次开源经历中,最重要的是什么事情?是最后的结果么?”我想可能不是。当我们去做任何一件事情的时候,都无法预料到下一秒会发生什么,更不会预料到最后的结果会是什么样子,所以结论并不适合放在开源经历的第一位。正所谓兴趣是最好的老师,与其猜测未知的结果,不如遵从本心去体会在开源中遇到的所有感受。因此,**一次成功的硕果固然可喜,但更重要的是享受过程。** - -我们可以对于开源项目的任何事情畅所欲言,可以发表自己对开源项目的理解,可以讨论目前存在的问题,还可以从交流中了解到更加广阔的开源世界。当然,开源社区不会是只有一种声音,我们可以有不同的观点,可以有分歧和争辩,还可以享受每一次思想的碰撞。除了必要的社区准则以外,我们的文字、代码以及思想都是无比自由的,或许这就是开源精神带给我的一种体验。 - -既然谈到了开源精神,那么一群志同道合的秉承开源精神的小伙伴自然是必不可少的。在此,要感谢在开源指北项目中帮助和鼓励过我的小伙伴们: - -- 感谢 [jack960330](https://gitee.com/jack960330) 对我编写修订过程中给予的专业指点,也感谢耐心的讲解和对我的认可,钦佩你的专业态度。 - -- 感谢 [taotieren](https://gitee.com/taotieren) 的中文排版指北项目,在了解一种排版规范的同时,还发现其使用的 WTFPL 开源协议——一个有趣的协议以及背后有趣的小故事。 - -- 感谢众多的开源小伙伴,我们一起沟通探讨了很多开源小知识,也通过他们了解到了很多开源项目,一起奋战的日子会是一段非常美好的回忆! - -- 感谢 Gitee 小助手带我加入开源小队,还给我邮递了那么多奖品,我会继续努力的。不辜负每一次参与! -- 感谢与开源指北的不期而遇,这是我这个冬季里最温暖的“小太阳”。 - -“琴罢辄举酒,酒罢辄吟诗”,这是我理想中的开源世界。所谓“琴”、“酒”、“诗”,是代指令自己感到美好的事物——是得到认可的喜悦,是有所收获的满足,是感受到如鱼得水般的自由。我觉得开源指北就是这样的,希望它在未来成长的路上,依旧如此自由!也希望参与开源的你——**Forever to be free !** \ No newline at end of file +--- +title: “我的一剂良药”之开源指北 +author: 西狩 +date: 2021-01-22 +permalink: /story/ouuan +--- + +## 开篇 + +开源指北是 Gitee 开源社区送给所有开源人的一份保姆级开源百科,它的出现让开源相关知识不再像“沧海遗珠”一样散落在瀚海苍茫,让初识开源者可以从容地面对开源之海的首次“起航”,让众多热衷开源的开源爱好者在这里畅谈其所想。 + +不得不说,开源指北项目的发起是一个非常有趣的想法,其秉持着“开源问题由开源来解决”的思想,吸引了众多开源爱好者参与到这项开源运动中来,我也是其中一员。这是我参与的第一个开源项目,在拟定标题时再三思忖,结合自身的亲身感受,最终定了这个标题。至于为什么说对我而言是“一剂良药”,在下文中我会作出解释。 + +相比“满满的正能量”,我更希望从平常视角坦诚相待,有喜悦,有悲伤,有勇往直前,有踟蹰迷茫。不管读到这篇文章的你正拥有着哪种情绪,都能从这些稀松平常的小事中有所得,然后继续努力前行,成为更好的自己。 + +接下来,分享一段普普通通、简简单单的故事。 + +## 源起 + +**“青山若无素,偃蹇不相亲。要识庐山面,他年是故人。”** + +我叫西狩,有些朋友也会叫我老江,从事 Java 开发相关工作。 + +2020年是动荡的一年。从我的大脑里进行热词分析,浮现出来了很多“动荡”的词汇。比如:“疫情”、“大选”、“制裁”、“猝死”、“内卷”等等。我们深知处在一个贩卖焦虑的时代,但有时还是会不自觉地被这些外界的焦虑所影响,对于处在人生各种分岔路口的人们而言,受到的影响可能会更大。随着时间越走越快,看到很多新鲜的事物如雨后春笋般破土而出,陌生而又新奇。就像是面对琳琅满目的商品一样,一不小心便挑花了眼。这时我们可能会迷茫,但我们深知,自己需要去做些什么来面对它们。 + +我不确定每个人是否都有过这种迷茫的经历,但就我个人而言,迷茫期是经常的,也是正常的。生活是一座围城,选择了漂泊但又渴望稳定,选择了努力但又渴望闲适。“有的人想得多却做得少”,我不确定这句话是否符合自己,但我深知自己做得还远远不够。大家应该都听过这样一句话:“学习最好的时间是十年前,其次是现在”。所以,**不要害怕迷茫,只要敢于面对迷茫并踏出下一步,那就是有意义的。** + +我不确定命运是否会眷顾内心和自己拧巴的人,但能够参与一项有意义的开源活动,我觉得自己是幸运的。一切的源头是从日常阅读公众号文章开始讲起,几个月前 [张乘辉](https://github.com/objcoding) 老师的一篇推文《使用 Hexo + Gitee 快速搭建属于自己的博客》,文章内容很简单易懂,而后我开始考虑搭建自己的博客。在搭建过程中,我 Gitee 平台上无意间看到了开源指北的开源活动,怀着一颗好奇心的自己就这样与开源指北相遇了。说实话,虽然平时也会在 Github、Gitee 上转一转,但顶多都是走马观花似的了解,并没有参与到什么开源项目中。起初自己也是随便了解一下。在了解项目简介、阅读其中几篇文章后,感觉自己对一些内容有一定的认知和共鸣,而且内容还有很多缺失,于是便尝试提交了一次 PR。 + +故事讲到这里,我可能还并不会深陷其中。在提交后的第二天,官方小伙伴 [tenngo](https://gitee.com/tenngoxars) 就合并了我的 PR。及时的正向反馈让我受到了很大的鼓舞,就像是可治百病的“一剂良药”,使我无处安放的心静了下来。于是便开始了我的第一次开源之旅。 + +## 指天说地 + +**“一点浩然气,千里快哉风。”** + +在开源指北之前,其实网络上有很多开源知识的相关文章,但太过零散,不成体系,对于想要参与开源的人并不友好。开源指北最大的意义就是对开源知识的整合,它涵盖了大部分常见的入门知识,可以帮助很多想要参与开源而不知如何入手的小伙伴,所以,我想有必要分享一下在开源指北参与过程中的感受与收获。 + +在《降临》中,有句台词让我记忆深刻:“If you immerse yourself into a foreign language, you can actually rewire your brain”。正如前文提到的迷茫期,最近一年的时间里发生了很多事情,思绪万千但却发现脚步却慢了下来。当我下意识提起自己的脚步时,却感觉似乎前方全是岔路,就在这时,开源指北出现了。在参与过程中,无论是查阅资料,还是编写文章,又或是提交 PR,都能感受到开源带给自己的活力。仔细想想,当自己毕业时,不愿在一眼望到头的生活里度过一生,那么自己对未来的迷茫和担忧就可以很好地接收了,因为这就是自己想要的生活。人生在世,不如意事常八九,大多数人都并非是一帆风顺的。**与其每日杞人忧天,不如沉下心来倾听内心的想法,然后坚定地踏出接下来的每一步。** + +在开始分享开源过程中的感悟前,先谈及了心态,是因为自己深知心态对我的重要性。在自己心静下来后,做事情的效率会有明显的提高,并且在交流、沟通以及决策上都可以更加清醒。接下来,便带着这份心态聊到哪算哪喽! + +开源与我的本职专业有着密切的联系,虽然是第一次参与开源,但自己对开源并不算陌生。曾经怀着激动的心情参加的每次 Pivotal 技术峰会、各种技术的 Meetup 以及各位大佬的技术分享,在这一刻似乎派上了一定的用场。这也说明了**平日积累的重要性**,碎片化学习虽然并不能建立起心中的一套完整的框架体系,但对自己的影响是潜移默化的。我会对每个章节进行阅读,文章结构不顺就梳理结构,上下文衔接问题就修改上下文,明显出现内容缺失就通过查阅资料再加上自己的理解进行补充。后面又进行了反复的阅读,以及关注小伙伴们提交的 PR。我们会为项目中提及的“半开源”的概念展开探讨,会对开源知识互相交流以至于忘记时间,诸如 arch、CLA、中国第一个被 OSI 认可的协议等等。我们也会因为项目中的不足而争辩,而且可能最终谁也说服不了谁,大家的思想是平等的,没有对错,而最终的结论也是有趣而一致的。那么这个结论是什么呢?其实很简单,各自提交 PR 就好了。**求同存异是开源社区的不二法则,我不认可你的观点,但我尊重你表达思想的权利。** + +因工作需要,我在 2017 年加入了 Kettle 技术交流群,经过学习掌握了它,但由于后续没有机会再使用,我对 Kettle 的熟练程度大幅度下降,更不要说现在最新的开源版本。同样的原因,我在 2019 年初加入了 Skywalking 交流群,基本属于一个“潜水者”,只是经常会查看技术交流的消息。其他社群我就不一一列举了,我之所以提到这两段经历,是想反思一下自己:为什么曾经有那么多优秀的开源项目摆在自己面前,到现在自己还是一个开源小白?我感觉有两个重要的事情自己没有做得很好:**坚持和思维模式**。 + +- 参与开源不是一蹴而就的事情,我们需要花费大量的时间来将其打造成为一个更好的东西。我因为不再使用而放弃对 Kettle 的关注,所以它自然而然就离我远去了。**其实大多数人都并非天才,能成为一个项目中优秀开源者的主要原因就是坚持。** +- 我学习 Kettle 只想使用它来解决问题,但从未想过自己还可以改变它。如果保持这样的思维模式继续下去,那么坚持的意义就是十分有限的了,因为我只是一个熟练工,可能永远都无法突破成为建筑师。**一个目标是否能够可达,有时候需要的只是一个思维的转变。** + +最近看了吴晟老师在开放原子基金会 2020 年技术峰会上发表的演讲——[开源运营治理分论坛 - Educate Community Over Support Community](https://www.bilibili.com/video/BV125411E7GK?p=1&share_medium=iphone&share_plat=ios&share_source=QQ&share_tag=s_i×tamp=1611211180&unique_k=ZKplUv)。演讲中很清晰地为大家讲解了我们在开源中应该关注的重点,解释了社区各种角色的职责,也谈及了对社区发展和社区生态的看法。当然,其中让人受益匪浅的内容还有很多,而且没有太多难理解的技术,更多的是对开源经验的分享,感兴趣的小伙伴可以了解一下。这也是我的一个小建议:**多去与他人交谈,倾听他人的想法,我们需要在思想碰撞的过程中不断刺激自己进行思维升级。** + +再分享一则个人觉得有趣的事情,每个开源项目都有自己的排版规则,在参与开源指北过程中,我在一个关于排版的开源项目中发现了一个有趣的协议:WTFPL。参考知乎问答“[什么是 WTFPL(Do What the Fuck You Want to Public License),为什么会有人使用这一授权许可?](https://www.zhihu.com/question/20865060/answer/51757033)”中的描述来了解一下: + +> 由于程序拥有所有权,所以每段代码允许大家在何种程度上自然使用就成为了一个严肃的法律问题,所以就诞生了licence这个概念。其中有一些代码是写出来让大家随意免费使用的,所以licence就要规定你可以干一切事情。可是在法律里,“允许你干任何事情”这句话并不严谨,所以随着不断的诉讼、打官司、法学家的诠释,诞生了诸如 [@IAMSK](http://www.zhihu.com/people/c55d6c118b9141f20776588b0308e586) 所说的一大堆授权协议。 +> 但是问题来了。 +> 这个协议是给程序员看的,却是由法学家和律师写的。 +> 于是随着时间的推移,这些协议变得unreadable,也就是程序员根本不可能看懂。 +> +> 而这些协议还会越来越长,随着欧美法律不断地被新的判例充实。。。。 +> +> 于是一些程序员为了反抗这一恶性循环,发明了WTFPL。 +> +> 简而言之,就是:**“你TM爱干啥干啥”** + +有趣的点在于,我仿佛能脑补出当时程序员看到冗长的法律条文和专业名词的时候抓狂的面部表情,是个很有意思的小故事。 + +最后要说一下,个人认为,开源指北项目参与门槛并不高,虽然在内容上会尽力做到精益求精,但它的受众是每一个开源人,大家都可以在这里各抒己见。这个项目的维护也会一直开放,也希望能够在以后听到更多开源故事和开源声音。**毕竟开源这件事儿,一起热闹起来才好玩嘛!** + +## 北窗之友 + +**“今日北窗下,自问何所为,欣然得三友,三友者为谁?琴罢辄举酒,酒罢辄吟诗。”** + +如果说有人问:“一次开源经历中,最重要的是什么事情?是最后的结果么?”我想可能不是。当我们去做任何一件事情的时候,都无法预料到下一秒会发生什么,更不会预料到最后的结果会是什么样子,所以结论并不适合放在开源经历的第一位。正所谓兴趣是最好的老师,与其猜测未知的结果,不如遵从本心去体会在开源中遇到的所有感受。因此,**一次成功的硕果固然可喜,但更重要的是享受过程。** + +我们可以对于开源项目的任何事情畅所欲言,可以发表自己对开源项目的理解,可以讨论目前存在的问题,还可以从交流中了解到更加广阔的开源世界。当然,开源社区不会是只有一种声音,我们可以有不同的观点,可以有分歧和争辩,还可以享受每一次思想的碰撞。除了必要的社区准则以外,我们的文字、代码以及思想都是无比自由的,或许这就是开源精神带给我的一种体验。 + +既然谈到了开源精神,那么一群志同道合的秉承开源精神的小伙伴自然是必不可少的。在此,要感谢在开源指北项目中帮助和鼓励过我的小伙伴们: + +- 感谢 [jack960330](https://gitee.com/jack960330) 对我编写修订过程中给予的专业指点,也感谢耐心的讲解和对我的认可,钦佩你的专业态度。 + +- 感谢 [taotieren](https://gitee.com/taotieren) 的中文排版指北项目,在了解一种排版规范的同时,还发现其使用的 WTFPL 开源协议——一个有趣的协议以及背后有趣的小故事。 + +- 感谢众多的开源小伙伴,我们一起沟通探讨了很多开源小知识,也通过他们了解到了很多开源项目,一起奋战的日子会是一段非常美好的回忆! + +- 感谢 Gitee 小助手带我加入开源小队,还给我邮递了那么多奖品,我会继续努力的。不辜负每一次参与! +- 感谢与开源指北的不期而遇,这是我这个冬季里最温暖的“小太阳”。 + +“琴罢辄举酒,酒罢辄吟诗”,这是我理想中的开源世界。所谓“琴”、“酒”、“诗”,是代指令自己感到美好的事物——是得到认可的喜悦,是有所收获的满足,是感受到如鱼得水般的自由。我觉得开源指北就是这样的,希望它在未来成长的路上,依旧如此自由!也希望参与开源的你——**Forever to be free !** diff --git "a/src/story/stories/\344\274\227\351\207\214\345\257\273\345\245\271\345\215\203\347\231\276\345\272\246\344\271\213DolphinScheduler.md" "b/src/story/stories/\344\274\227\351\207\214\345\257\273\345\245\271\345\215\203\347\231\276\345\272\246\344\271\213DolphinScheduler.md" index 1eefab2787845cb173044f7a2e5736ef79690ceb..c2e9f301ff9e370225e36ea06423de1658fbb1a9 100644 --- "a/src/story/stories/\344\274\227\351\207\214\345\257\273\345\245\271\345\215\203\347\231\276\345\272\246\344\271\213DolphinScheduler.md" +++ "b/src/story/stories/\344\274\227\351\207\214\345\257\273\345\245\271\345\215\203\347\231\276\345\272\246\344\271\213DolphinScheduler.md" @@ -1,68 +1,65 @@ ---- -title: 众里寻她千百度之 DolphinScheduler -author: CalvinKirs -date: 2021-01-15 -permalink: /story/calvinkirs ---- - - -## 前述 -### 关于我 -我是CalvinKirs,目前是 Apache DolphinScheduler 的 Commiter。擅长大数据 olap、大数据调度、分布式组件开发等。目前专注于大数据领域核心技术研发。 -我也是一名开源爱好者,我要讲的是我从起始给 DolphinScheduler 做贡献到近期加入到易观数科大家庭的故事。 - -### 关于 Apache DolphinScheduler社区 -Apache DolphinScheduler(incubator) 于17年在易观数科立项,19年3月开源, 19 年8月进入 Apache 孵化器,社区发展非常迅速,目前已有 400+ 公司在生产上使用,代码+文档贡献者近200位,社区用户4000 +人。DolphinScheduler (简称DS) 致力于使大数据任务调度开箱即用,它以拖拉拽的可视化方式将各种任务间的关系组装成 DAG(有向无环图),并实时监控整个数据pipeline的运行状态,同时支持失败重试、重跑、恢复失败、补数等大数据常用操作 - - -## 遇见DolphinScheduler - -我是一个有开源情节的人,开源以不同的方式陪伴了我相当长的一段时间,同样也给我带来了一些比较大的改变。 - -我个人接触的开源项目是比较多的,但是深度贡献的并不多,也是一个偶然的契机接触到DolphinScheduler,从此开始了深度贡献。 - -选择对味的社区其实很重要,如同恋爱一般,总需要几个回合摸索试探才能决定是否合适,DolphinScheduler社区给我的一个最大的感受就是足够包容,我不认同你,但是我支持你。这是[dailidong](https://github.com/dailidong)给我的一个最直观的感受,你的想法不成熟的时候,作为PPMC,他需要对社区负责,他可能不是很认同,但是他支持你去完善去佐证,这个过程中也是很感谢社区的一些其他伙伴,[qiaozhanwei](https://github.com/qiaozhanwei)、[Tboy](https://github.com/Technoboy-)、[gaojun2048](https://github.com/gaojun2048),[lgcarrer](https://github.com/lgcareer)(license的大佬)、[lenboo](https://github.com/lenboo)(核心流程找他就对了)等,一开始我总有种人微言轻的感觉,一般都处在旁听的状态,毕竟这些贡献者基本上都是各大公司的精英人物。后来发现是我多虑了,大神们其实非常平易近人。也是因为这些人,让我喜欢上DolphinScheduler社区。 - -## 社区带给我的影响 - -随着社区的发展,越来越多同学的加入,我们可能(甚至是必然)会在一些设计上存在一些不同的意见,但这其实也是开源的魅力,对于社区来讲,也是一种好事,不同思想的碰撞才会导致设计趋近于更加完善。也只有这样,DolphinScheduler才能更好走向全球。当然,对于个人来讲,也是一种提升,就我而言,我之前在社区讨论关于通讯序列化方案的想法,我们的导师,[吴晟老师](https://github.com/wu-sheng)问我,为什么不选择protobuf呢,我以前的认知,只体现在一个很片面的范围内,但是吴晟老师从更高层次回答了我所谓的protobuf鸡肋的地方,这确实打开了我的视野。感兴趣的可以去搜邮件列表,我所想要表达的是,开源是一个全球的舞台,会有各种不同的人进来参与,也正是由于这样,你的提升才会更大,因为你不再停留在原有的圈子原有的认知去思考,你会接受各种各样的人来进行review(不仅仅是code,同样包括一些设计等等),这种过程其实也是在逐渐拓宽自己的专业领域与认知。 - -## DolphinScheduler微内核插件化设计 - -项目的推进导致架构的变化,捐给Apache之后,意味着你要面向全球的用户,不同的用户对于不同场景的需求是不同的,我们更希望的是DolphinScheduler作为一个基础设施提供给用户,给用户提供强大的扩展能力,用户在DolphinScheduler这个平台上去快速扩充自己的功能。 - -在2020年(近期会发版),[高俊老师](https://github.com/gaojun2048)提出了微内核插件化的架构设计,拿alert来讲,我们alert发版后是支持五种告警方式,这能够满足绝大多数用户的一个需求,但依然有一些需求是没办法满足的,这个时候用户想要自己实现其实很简单,他不需要系统的去了解DolphinScheduler的整个架构,只需要关注alert的扩展接口,对于其他功能来讲是完全隔离的(这也意味着你降低了污染传递,当你的模块出现问题的时候,你不会过多影响其他模块,甚至你可以完全移除你自己的插件),这对于用户来讲,理解成本更低、开发成本测试成本同样更低,对于贡献者来讲亦是如此,降低贡献者门槛,才能使得一个项目走的更远,曲高和寡,对于开源项目来讲同样如此,DolphinScheduler社区目前有很多其他社区的贡献者,比如SkyWalking、ShardingSphere、Dubbo、TubeMq等,调度系统更是与其他大数据生态紧密结合,我们也是希望,通过微内核插件化的方式,使得各个领域的专家都可以以最低成本的贡献进来。 - -## 开源的乐趣 - - -[姜宁老师](https://github.com/WillemJiang)讲,开源社区其实是一帮对的人才能够聚在一起,这种过程会让你很享受,我之前收到过一封邮件,是一个印度贡献者的,我merge了他参与Apache DolphinScheduler的第一个PR,他写了大概几百字的一封邮件,表达对于开源的向往以及询问我后续参与贡献的一个途径,我不太确定这是否会导致他从此踏上开源这条路,成为一个深度贡献者,但至少对于他来讲,这一刻他有了深度参与的一个想法,我当时也是因为首次贡献被merge之后于是踏上了开源这条路,我至今依然记得我对于Apache的第一个PR,虽然小,甚至从今天看来,那可能是我贡献的PR中最微不足道的一个,但对于我来讲,它为我打开了一扇门,所以其实到今天,我很乐意给那些初次贡献的贡献者提供深度的一个帮助,帮他们认识开源、走进开源。曾经有人为我打开了一扇门,那我希望我能够给更多的人提供走进这扇门的一个帮助,这可能也是一种属于开源人的传承(BTW,强烈推荐[ALC BeiJing](https://github.com/alc-beijing))。 - -马斯洛需求层次理论中讲到人的高级需求,其实对我来讲,通过DolphinScheduler,我达到了自我实现与尊重。 - -当我写的代码,会运行在数万台服务器上,影响几亿的用户,我也是第一次感觉作为个体和这个世界有了更加紧密的一个联系,这种内心的成就感是非常高的。 - -当我看到被我merge代码的同学发朋友圈或者邮件的时候,我内心其实也是非常愉快的,我老板说:优秀的人成就自己,卓越的人成就他人,我可能不是很优秀的人,但如果能够从一件小事上影响到别人,对于我来讲,我也是很愉悦的(成年人的快乐有时候就这么简单)。 - - -## 尾篇 致下一个贡献者的你 - -[大侠](https://github.com/William-GuoWei)在ALC Beijing-开源到底有多难中以[开源,不是天才的甜点,而是勤奋者的盛宴](https://zhuanlan.zhihu.com/p/208577284)为题的分享有几句话是比较触动我的 -``` -“中国没有开源”这个观点我是不愿意相信的。我相信这一代年轻人,不仅仅是程序猿,而是越来越多的人,愿意参加到各行各业的非盈利团体当中去,贡献自己的想法、代码、知识,让这个世界变得更加美好。 - - - -我相信哪怕我们这一代人看不到开源的春天,我们的下一代人也不应该再看到开源的“雾霾天”。于是我们就积攒了更多的力量,筹备了一年,把我们自己内部使用的一个产品 — Dolphin Scheduler 进行了开源。 -``` -我身边参与开源的人其实蛮多的,但倘若放到整个公司来讲,其实也并不多,上家公司,产研三四百多人,但是是Apache commiter或者PMC的仅仅只有三人,然而我们整个基础设施一大半是在开源软件的基础上进行开发的(其中一大半是ASF的),对于所使用到的开源项目,我们基本都是内部单独维护了一个分支,这样做当然有好处,我们可以跑的很快,有什么问题可以很快修复,但是很少有人会把这些贡献给上游,最终结果导致和上游差异过大,彻底和社区脱节。大家的现状是很忙,没有时间思考,大多数人不断的掉进坑里面再爬出来,但如果每个人都做出一点点努力,那么这样其实成本是最少的。你贡献一点,他贡献一点,那么其实我们的工作量会减少很多,因为社区帮你做了。这也是开源的力量,还是回到那句话,一个人可以走的很快,但一群人可以走得很远。 - - -熟悉吴晟老师的人都知道吴晟老师喜欢用『各怀鬼胎』来形容开源社区,我想说的是,无论你怀有什么样的心思(又或者仅仅是单纯的喜欢开源),透过开源确实可以帮你达到一些需求的满足,无论是一份光鲜的履历,或者一份 good job,或者隐形的人脉、技术实力的提升、多一点谈资等等。但这个前提是你去参与,去贡献。(BTW,我本人其实也是开源的受益者,因为参与开源,我有幸加入了易观,大多数企业对于开源贡献者还是比较友好的,吴晟老师的一次[分享](https://www.bilibili.com/video/BV17Q4y1N7iA),有数据显示:87%的雇主希望招聘到具备开源能力的员工,而55%的开源业内人士表示他们可以轻松地找到一份新工作。) - -中国并不缺乏优秀的工程师,缺乏的仅仅是如何正确的认识开源,参与开源。今天的中国开源其实已经非常好了,有很多前辈以及组织在开源这个领域为我们进行铺路布道,比如开源社、ALC Beijing等,我们所缺少的,仅仅是大家的参与。有一句很老套的话:如果不是现在,那是什么时候?如果不是你,那会是谁?我是[CalvinKirs](https://github.com/CalvinKirs),我在[DolphinScheduler](https://github.com/apache/incubator-dolphinscheduler)社区等你。 - - - - - +--- +title: 众里寻她千百度之 DolphinScheduler +author: CalvinKirs +date: 2021-01-15 +permalink: /story/calvinkirs +--- + + +## 前述 +### 关于我 +我是 CalvinKirs,目前是 Apache DolphinScheduler 的 Commiter。擅长大数据 olap、大数据调度、分布式组件开发等。目前专注于大数据领域核心技术研发。 + +我也是一名开源爱好者,我要讲的是我从起始给 DolphinScheduler 做贡献到近期加入到易观数科大家庭的故事。 + +### 关于 Apache DolphinScheduler 社区 +Apache DolphinScheduler(incubator)于2017年在易观数科立项,2019年3月开源,2019年8月进入 Apache 孵化器,社区发展非常迅速,目前已有 400+ 公司在生产上使用,代码+文档贡献者近 200 位,社区用户 4000 多人。 + +DolphinScheduler(简称 DS)致力于使大数据任务调度开箱即用,它以拖拉拽的可视化方式将各种任务间的关系组装成 DAG(有向无环图),并实时监控整个数据 pipeline 的运行状态,同时支持失败重试、重跑、恢复失败、补数等大数据常用操作。 + + +## 遇见 DolphinScheduler + +我是一个有开源情节的人,开源以不同的方式陪伴了我相当长的一段时间,同样也给我带来了一些比较大的改变。 + +我个人接触的开源项目是比较多的,但是深度贡献的并不多,也是一个偶然的契机接触到 DolphinScheduler,从此开始了深度贡献。 + +选择对味的社区其实很重要,如同恋爱一般,总需要几个回合摸索试探才能决定是否合适,DolphinScheduler 社区给我的一个最大的感受就是足够包容,我不认同你,但是我支持你。这是 [dailidong](https://github.com/dailidong) 给我的一个最直观的感受,你的想法不成熟的时候,作为 PPMC,他需要对社区负责,他可能不是很认同,但是他支持你去完善去佐证,这个过程中也是很感谢社区的一些其他伙伴,[qiaozhanwei](https://github.com/qiaozhanwei)、[Tboy](https://github.com/Technoboy-)、[gaojun2048](https://github.com/gaojun2048)、[lgcarrer](https://github.com/lgcareer)(license 的大佬)、[lenboo](https://github.com/lenboo)(核心流程找他就对了)等,一开始我总有种人微言轻的感觉,一般都处在旁听的状态,毕竟这些贡献者基本上都是各大公司的精英人物。后来发现是我多虑了,大神们其实非常平易近人。也是因为这些人,让我喜欢上 DolphinScheduler 社区。 + +## 社区带给我的影响 + +随着社区的发展,越来越多同学的加入,我们可能(甚至是必然)会在一些设计上存在一些不同的意见,但这其实也是开源的魅力,对于社区来讲,也是一种好事,不同思想的碰撞才会导致设计趋近于更加完善。也只有这样,DolphinScheduler 才能更好走向全球。当然,对于个人来讲,也是一种提升,就我而言,我之前在社区讨论关于通讯序列化方案的想法,我们的导师,[吴晟老师](https://github.com/wu-sheng)问我,为什么不选择 protobuf 呢,我以前的认知,只体现在一个很片面的范围内,但是吴晟老师从更高层次回答了我所谓的 protobuf 鸡肋的地方,这确实打开了我的视野。感兴趣的可以去搜邮件列表,我所想要表达的是,开源是一个全球的舞台,会有各种不同的人进来参与,也正是由于这样,你的提升才会更大,因为你不再停留在原有的圈子原有的认知去思考,你会接受各种各样的人来进行 review(不仅仅是 code,同样包括一些设计等等),这种过程其实也是在逐渐拓宽自己的专业领域与认知。 + +## DolphinScheduler 微内核插件化设计 + +项目的推进导致架构的变化,捐给 Apache 之后,意味着你要面向全球的用户,不同的用户对于不同场景的需求是不同的,我们更希望的是 DolphinScheduler 作为一个基础设施提供给用户,给用户提供强大的扩展能力,用户在 DolphinScheduler 这个平台上去快速扩充自己的功能。 + +在2020年(近期会发版),[高俊老师](https://github.com/gaojun2048)提出了微内核插件化的架构设计,拿 alert 来讲,我们 alert 发版后是支持五种告警方式,这能够满足绝大多数用户的一个需求,但依然有一些需求是没办法满足的,这个时候用户想要自己实现其实很简单,他不需要系统的去了解 DolphinScheduler 的整个架构,只需要关注 alert 的扩展接口,对于其他功能来讲是完全隔离的(这也意味着你降低了污染传递,当你的模块出现问题的时候,你不会过多影响其他模块,甚至你可以完全移除你自己的插件),这对于用户来讲,理解成本更低、开发成本测试成本同样更低,对于贡献者来讲亦是如此,降低贡献者门槛,才能使得一个项目走的更远,曲高和寡,对于开源项目来讲同样如此,DolphinScheduler 社区目前有很多其他社区的贡献者,比如 SkyWalking、ShardingSphere、Dubbo、TubeMq 等,调度系统更是与其他大数据生态紧密结合,我们也是希望,通过微内核插件化的方式,使得各个领域的专家都可以以最低成本的贡献进来。 + +## 开源的乐趣 + +[姜宁老师](https://github.com/WillemJiang)讲,开源社区其实是一帮对的人才能够聚在一起,这种过程会让你很享受。我之前收到过一封邮件,是一个印度贡献者的,我 merge 了他参与 Apache DolphinScheduler 的第一个 PR,他写了大概几百字的一封邮件,表达对于开源的向往以及询问我后续参与贡献的一个途径,我不太确定这是否会导致他从此踏上开源这条路,成为一个深度贡献者。但至少对于他来讲,这一刻他有了深度参与的一个想法,我当时也是因为首次贡献被 merge 之后于是踏上了开源这条路。我至今依然记得我对于 Apache 的第一个 PR,虽然小,甚至从今天看来,那可能是我贡献的 PR 中最微不足道的一个,但对于我来讲,它为我打开了一扇门,所以其实到今天,我很乐意给那些初次贡献的贡献者提供深度的一个帮助,帮他们认识开源、走进开源。曾经有人为我打开了一扇门,那我希望我能够给更多的人提供走进这扇门的一个帮助,这可能也是一种属于开源人的传承(BTW,强烈推荐 [ALC BeiJing](https://github.com/alc-beijing))。 + +马斯洛需求层次理论中讲到人的高级需求,其实对我来讲,通过 DolphinScheduler,我达到了自我实现与尊重。 + +当我写的代码,会运行在数万台服务器上,影响几亿的用户,我也是第一次感觉作为个体和这个世界有了更加紧密的一个联系,这种内心的成就感是非常高的。 + +当我看到被我 merge 代码的同学发朋友圈或者邮件的时候,我内心其实也是非常愉快的,我老板说:优秀的人成就自己,卓越的人成就他人,我可能不是很优秀的人,但如果能够从一件小事上影响到别人,对于我来讲,我也是很愉悦的(成年人的快乐有时候就这么简单)。 + + +## 尾篇 致下一个贡献者的你 + +[大侠](https://github.com/William-GuoWei)在 ALC Beijing-开源到底有多难中,以《[开源,不是天才的甜点,而是勤奋者的盛宴](https://zhuanlan.zhihu.com/p/208577284)》为题的分享有几句话是比较触动我的。 + +> “中国没有开源”这个观点我是不愿意相信的。我相信这一代年轻人,不仅仅是程序猿,而是越来越多的人,愿意参加到各行各业的非盈利团体当中去,贡献自己的想法、代码、知识,让这个世界变得更加美好。 +> +> 我相信哪怕我们这一代人看不到开源的春天,我们的下一代人也不应该再看到开源的“雾霾天”。于是我们就积攒了更多的力量,筹备了一年,把我们自己内部使用的一个产品 — Dolphin Scheduler 进行了开源。 + +我身边参与开源的人其实蛮多的,但倘若放到整个公司来讲,其实也并不多,上家公司,产研三四百多人,但是 Apache commiter 或者 PMC 的仅仅只有三人,然而我们整个基础设施一大半是在开源软件的基础上进行开发的(其中一大半是 ASF 的),对于所使用到的开源项目,我们基本都是内部单独维护了一个分支,这样做当然有好处,我们可以跑的很快,有什么问题可以很快修复,但是很少有人会把这些贡献给上游,最终结果导致和上游差异过大,彻底和社区脱节。大家的现状是很忙,没有时间思考,大多数人不断的掉进坑里面再爬出来,但如果每个人都做出一点点努力,那么这样其实成本是最少的。你贡献一点,他贡献一点,那么其实我们的工作量会减少很多,因为社区帮你做了。这也是开源的力量,还是回到那句话,一个人可以走的很快,但一群人可以走得很远。 + + +熟悉吴晟老师的人都知道吴晟老师喜欢用『各怀鬼胎』来形容开源社区,我想说的是,无论你怀有什么样的心思(又或者仅仅是单纯的喜欢开源),透过开源确实可以帮你达到一些需求的满足,无论是一份光鲜的履历,或者一份 Good job,或者隐形的人脉、技术实力的提升、多一点谈资等等。但这个前提是你去参与,去贡献。(BTW,我本人其实也是开源的受益者,因为参与开源,我有幸加入了易观,大多数企业对于开源贡献者还是比较友好的,吴晟老师的一次[分享](https://www.bilibili.com/video/BV17Q4y1N7iA),有数据显示:87% 的雇主希望招聘到具备开源能力的员工,而 55% 的开源业内人士表示他们可以轻松地找到一份新工作。) + +中国并不缺乏优秀的工程师,缺乏的仅仅是如何正确的认识开源,参与开源。今天的中国开源其实已经非常好了,有很多前辈以及组织在开源这个领域为我们进行铺路布道,比如开源社、ALC Beijing 等,我们所缺少的,仅仅是大家的参与。有一句很老套的话:如果不是现在,那是什么时候?如果不是你,那会是谁?我是 [CalvinKirs](https://github.com/CalvinKirs),我在 [DolphinScheduler](https://github.com/apache/incubator-dolphinscheduler) 社区等你。 + + diff --git "a/src/story/stories/\345\220\221\345\276\256\350\275\257\345\256\230\346\226\271\350\264\241\347\214\256 @types \345\214\205.md" "b/src/story/stories/\345\220\221\345\276\256\350\275\257\345\256\230\346\226\271\350\264\241\347\214\256 @types \345\214\205.md" index 488d5e3fe24148f0f1da8671a28f4c35db145066..a5fe12f94689035dbc4f06d3bde46ec382f32a25 100644 --- "a/src/story/stories/\345\220\221\345\276\256\350\275\257\345\256\230\346\226\271\350\264\241\347\214\256 @types \345\214\205.md" +++ "b/src/story/stories/\345\220\221\345\276\256\350\275\257\345\256\230\346\226\271\350\264\241\347\214\256 @types \345\214\205.md" @@ -27,7 +27,7 @@ permalink: /story/yangjunning DefinitelyTyped 目前是由微软官方维护的开源项目,参与的方式和 Homebrew 差不多,都是基于 GitHub 的工作流: -1. fork [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) 到自己的账号下 +1. Fork [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) 到自己的账号下 2. 添加自己的包并编写类型声明 3. 提交 PR 4. 官方 review 并合并发布到 NPM @@ -97,3 +97,4 @@ yarn lint tuya-panel-kit 1. [dtslint](https://github.com/microsoft/dtslint) :微软专门写的用来检验类型声明文件的工具。正是因为它,我做了大量优化工作。 2. 机器人 🤖(dt-mergebot、dt-review-bot、typescript-bot-watchdog):在你的代码通过所有规范之前,都是这些机器人在和你交互。大家感兴趣的话,之后我会单独出一篇解析的文章 3. 尽职尽责的维护:虽然有时 review 速度明显很慢(可能因为国外疫情)。但是这些维护者真的是尽职尽责的 review 你的代码。机器再厉害也只是一个减少工作量的工具。我们应该致敬的还是这些为社区默默奉献的人。 + diff --git "a/src/story/stories/\345\274\200\346\272\220\346\234\211\351\255\224\345\212\233-DolphinScheduler\345\222\214\346\210\221\347\232\204\345\274\200\346\272\220\345\216\206\347\250\213.md" "b/src/story/stories/\345\274\200\346\272\220\346\234\211\351\255\224\345\212\233-DolphinScheduler\345\222\214\346\210\221\347\232\204\345\274\200\346\272\220\345\216\206\347\250\213.md" index 852cc56f8a86c54df3fa2e4e2167964cd59b4811..af0a790d43d5685f7b34b8353be1046ce4bb55a9 100644 --- "a/src/story/stories/\345\274\200\346\272\220\346\234\211\351\255\224\345\212\233-DolphinScheduler\345\222\214\346\210\221\347\232\204\345\274\200\346\272\220\345\216\206\347\250\213.md" +++ "b/src/story/stories/\345\274\200\346\272\220\346\234\211\351\255\224\345\212\233-DolphinScheduler\345\222\214\346\210\221\347\232\204\345\274\200\346\272\220\345\216\206\347\250\213.md" @@ -1,36 +1,36 @@ --- -title: 开源有魔力-DolphinScheduler和我的开源历程 +title: 开源有魔力,DolphinScheduler 和我的开源历程 author: leonbao date: 2021-01-20 permalink: /story/leonbao ---- +--- 鲍亮(leonbao),目前在易观数科大数据平台,负责平台建设工作,开源爱好者,DolphinScheduler PPMC, 一个有梦想的程序员。 ## 开源的思考 -“What's your Legacy?” 易观的大家长Edward在一次季度总结中曾提到这样一句话,引发了我对于legacy的思考:写出一个让世界上更多人使用的软件,这也许是大多数程序员的初心和梦想,而能让这种想法实现的就是开源。站在2021年的里程碑旁回首过去,DolphinScheduler已经在这条路上奔跑了2年。就像电影里的镜头一样,阿甘坚持不懈跑步,周围聚集了越来越多的同行者,越来越多的人加入到开发者队伍中,开源的魔力正在让我们的梦想照进现实。新年伊始,我想回忆一下我们的开源之路。 +“What's your Legacy?” 易观的大家长 Edward 在一次季度总结中曾提到这样一句话,引发了我对于 legacy 的思考:写出一个让世界上更多人使用的软件,这也许是大多数程序员的初心和梦想,而能让这种想法实现的就是开源。站在2021年的里程碑旁回首过去,DolphinScheduler 已经在这条路上奔跑了2年。就像电影里的镜头一样,阿甘坚持不懈跑步,周围聚集了越来越多的同行者,越来越多的人加入到开发者队伍中,开源的魔力正在让我们的梦想照进现实。新年伊始,我想回忆一下我们的开源之路。 + +2017年底,易观的千帆项目每天数百亿条数据,月活 6.2 亿,上万个任务需要处理近 7PB 的数据,用的调度系统,却年久失修,遇到问题就焦头烂额,对于新的需求也是束手无策,所以更换调度系统势在必行。众所周知,互联网公司用得最多的就是开源产品,我们调研了市面上主流的开源调度,比如 oozie、Azkaban、Airflow 等开源调度还有几个商业调度,均不能很好满足我们好用、易用的目标,所以站在众多开源产品的肩膀上,我们确定了以无中心为设计思想的架构。践行易观”数据能力平民化”的理念,最开始的时候我们就决定将此项目开源,故而将业务系统彻底与调度解耦,这也是最初设计的一个重要思想。 -2017年底,易观的千帆项目每天数百亿条数据,月活6.2亿,上万个任务需要处理近7PB的数据,用的调度系统,却年久失修,遇到问题就焦头烂额,对于新的需求也是束手无策,所以更换调度系统势在必行。众所周知,互联网公司用得最多的就是开源产品,我们调研了市面上主流的开源调度,比如oozie、Azkaban、Airflow等开源调度还有几个商业调度,均不能很好满足我们好用、易用的目标,所以站在众多开源产品的肩膀上,我们确定了以无中心为设计思想的架构。践行易观”数据能力平民化”的理念,最开始的时候我们就决定将此项目开源,故而将业务系统彻底与调度解耦,这也是最初设计的一个重要思想。 - -DS每个功能、每个流程的诞生都伴随着团队内的一场场激烈的思想碰撞、一次次不分昼夜的战斗。为了更快实现整个流程和验证产品的有效性,我们使用了最简单的数据库轮询方案,这也为提升并发量和减少资源消耗带来了不小的挑战,这两点和扩展性的优化也是DS将来最主要的任务。同时,也让我们认识到开源的魔力所在,只依靠一个小圈子做软件会产生局限性,有更多的开发者和思想交汇,产品才能更好得发展。 +DS 每个功能、每个流程的诞生都伴随着团队内的一场场激烈的思想碰撞、一次次不分昼夜的战斗。为了更快实现整个流程和验证产品的有效性,我们使用了最简单的数据库轮询方案,这也为提升并发量和减少资源消耗带来了不小的挑战,这两点和扩展性的优化也是 DS 将来最主要的任务。同时,也让我们认识到开源的魔力所在,只依靠一个小圈子做软件会产生局限性,有更多的开发者和思想交汇,产品才能更好得发展。 -当第一个版本出来以后,产品名字确定为易调度(EasyScheduler),CTO郭大侠曾提出理念”开箱即用”,简而言之就是一个“易“字,另一方面,在易观的企业文化中,“易”也可以拆分成日月两字,象征着变化即永恒。经过一系列的测试,又历经3个月时间,终于把千帆的任务都转移到易调度里面。后面又从各大朋友圈里找了一些种子用户验证产品的功能。2019年3月,经过一系列重构,发布了第一个开源版本1.0,并在github上开放所有源代码。 +当第一个版本出来以后,产品名字确定为易调度(EasyScheduler),CTO 郭大侠曾提出理念”开箱即用”,简而言之就是一个“易”字,另一方面,在易观的企业文化中,“易”也可以拆分成日月两字,象征着变化即永恒。经过一系列的测试,又历经3个月时间,终于把千帆的任务都转移到易调度里面。后面又从各大朋友圈里找了一些种子用户验证产品的功能。2019年3月,经过一系列重构,发布了第一个开源版本1.0,并在 GitHub 上开放所有源代码。 ## 开放源代码=开源? -开放源代码=开源?在了解ASF以前,我一直都是这么认为的。但其实,开源的目的不仅仅是能让更多人用上好的产品,更重要的是让更多的人来提高和完善这个调度系统,让它变得更易用,更好用,正所谓“独行快,众行远“。 - -在开放源代码以后的一段时间内,我们发现一个问题:并没有多少开发者加入,也没有新的代码和新的思想出现。后来各种不放弃的执着让我们遇到了Apache Kylin现在的VP史少峰老师,史老师给我们引荐了我们现在的Mentor陈亮老师和Champion - 吴晟老师,Apache SkyWalking Founder。在一个阳光明媚的下午,吴晟老师给我们普及了apache 相关知识,为我们打开了开源世界的新大门。”Community > Code”,决策透明才能让更多人加入,进而形成一个公平、平等、精英治理的社区。我们确定了新的目标:加入apache,建立apache way的社区。 - -加入apache当然没有那么容易,每个人对于apache way的理解也都不一样,在对项目的重构和升级过程中,大家又加入到充满激情的战斗中,纷纷在微信群里提出很多想法,这让我们认识到以前社区没有更多的开发者和思想,就是因为决策不透明。2019年8月底,经过前期准备,DS终于顺利进入孵化器,成为apache的孵化项目。 +开放源代码=开源?在了解 ASF 以前,我一直都是这么认为的。但其实,开源的目的不仅仅是能让更多人用上好的产品,更重要的是让更多的人来提高和完善这个调度系统,让它变得更易用,更好用,正所谓“独行快,众行远”。 + +在开放源代码以后的一段时间内,我们发现一个问题:并没有多少开发者加入,也没有新的代码和新的思想出现。后来各种不放弃的执着让我们遇到了 Apache Kylin 现在的 VP 史少峰老师,史老师给我们引荐了我们现在的 Mentor 陈亮老师和 Champion - 吴晟老师,Apache SkyWalking Founder。在一个阳光明媚的下午,吴晟老师给我们普及了 Apache 相关知识,为我们打开了开源世界的新大门。“Community > Code”,决策透明才能让更多人加入,进而形成一个公平、平等、精英治理的社区。我们确定了新的目标:加入 Apache,建立 Apache way 的社区。 + +加入 Apache 当然没有那么容易,每个人对于 Apache way 的理解也都不一样,在对项目的重构和升级过程中,大家又加入到充满激情的战斗中,纷纷在微信群里提出很多想法,这让我们认识到以前社区没有更多的开发者和思想,就是因为决策不透明。2019年8月底,经过前期准备,DS 终于顺利进入孵化器,成为 Apache 的孵化项目。 ## 我和社区的进步 -在一年多的孵化期间,我们走过很多弯路,也学到了很多宝贵的经验,社区也取得了很大的进步。为了更好了解apache,我个人读了很多书,学习了其他项目的代码,了解了其他社区的构建方式,这让我受益匪浅。社区也是一样,从最开始的第一个版本需要4个月发出,到现在基本上每个月都会发一个版本;从最开始的不知道怎么使用邮件列表到现在的大事小情都想通过邮件列表来通知和讨论;从最开始的迷惑于license,到现在对各种license都略知一二。。。 - -个人和社区都在不断发展,这一点正如ASF member姜宁老师的比喻:“在武林中立一个山头,带一群人成长“。每次通过邮件列表、issue、pull request的交流都像是在和不同的高手过招,在这个过程中,每个人都能学到新的招数,加深自己的内功。到目前为止,社区也贡献了很多有价值的功能,小到各种bug的fix、文档的注释, 大到各种重构、github action、k8s等等。 +在一年多的孵化期间,我们走过很多弯路,也学到了很多宝贵的经验,社区也取得了很大的进步。为了更好了解 Apache,我个人读了很多书,学习了其他项目的代码,了解了其他社区的构建方式,这让我受益匪浅。社区也是一样,从最开始的第一个版本需要4个月发出,到现在基本上每个月都会发一个版本;从最开始的不知道怎么使用邮件列表到现在的大事小情都想通过邮件列表来通知和讨论;从最开始的迷惑于 license,到现在对各种 license 都略知一二。 + +个人和社区都在不断发展,这一点正如 ASF member 姜宁老师的比喻:“在武林中立一个山头,带一群人成长“。每次通过邮件列表、issue、pull request 的交流都像是在和不同的高手过招,在这个过程中,每个人都能学到新的招数,加深自己的内功。到目前为止,社区也贡献了很多有价值的功能,小到各种 bug 的 fix、文档的注释, 大到各种重构、GitHub Action、K8s 等等。 ## 呼唤更多同行者 -从Dolphinscheduler诞生到现在,已经有超过150个代码贡献者和近50个文档贡献者加入我们的队伍,在“公平、开放、透明“的加持下,只要你怀有同样的初心,欢迎与我们同行,用开源的魔力把梦想变成现实! +从 Dolphinscheduler 诞生到现在,已经有超过 150 个代码贡献者和近 50 个文档贡献者加入我们的队伍,在“公平、开放、透明”的加持下,只要你怀有同样的初心,欢迎与我们同行,用开源的魔力把梦想变成现实! diff --git "a/src/story/stories/\345\274\200\346\272\220\347\244\276\345\214\272\345\256\236\344\271\240\350\256\260 - \346\210\221\346\212\212 openEuler \347\247\273\346\244\215\345\210\260\344\272\206 Windows WSL.md" "b/src/story/stories/\345\274\200\346\272\220\347\244\276\345\214\272\345\256\236\344\271\240\350\256\260 - \346\210\221\346\212\212 openEuler \347\247\273\346\244\215\345\210\260\344\272\206 Windows WSL.md" index 358f1141ba608736b6c6988c94789ade9e32065c..f1ef5ecb6f844d9c8703b75b194e99899d935d65 100644 --- "a/src/story/stories/\345\274\200\346\272\220\347\244\276\345\214\272\345\256\236\344\271\240\350\256\260 - \346\210\221\346\212\212 openEuler \347\247\273\346\244\215\345\210\260\344\272\206 Windows WSL.md" +++ "b/src/story/stories/\345\274\200\346\272\220\347\244\276\345\214\272\345\256\236\344\271\240\350\256\260 - \346\210\221\346\212\212 openEuler \347\247\273\346\244\215\345\210\260\344\272\206 Windows WSL.md" @@ -5,7 +5,7 @@ date: 2021-07-20 permalink: /story/wanghaitao --- -# 开源社区实习记 - 我把 openEuler 移植到了 Windows WSL + ![1](https://gitee.com/ouyanghaitao/images/raw/master/1.png) @@ -13,53 +13,53 @@ permalink: /story/wanghaitao 我叫王海涛,哈尔滨工业大学(深圳)校区计算机专业的大三学生。 -为了准备第一届全国大学生操作系统比赛,我的老师建议参加一些RISC-V相关的比赛,提前熟悉RISC-V,为从零写内核做好准备。于是我在2020年寒假期间参加了“2020 openEuler 高校开发者大赛”,选择的题目是“为openEuler-RISC-V添加Grub的引导启动方式”。从安装openEuler、注册gitee账号,再到用QEMU模拟RISC-V、学习Grub,这个比赛让我学到了操作系统启动流程相关的硬核知识,也让我开始了解openEuler开源社区。 +为了准备第一届全国大学生操作系统比赛,我的老师建议参加一些 RISC-V 相关的比赛,提前熟悉 RISC-V,为从零写内核做好准备。于是我在2020年寒假期间参加了“2020 openEuler 高校开发者大赛”,选择的题目是“为 openEuler-RISC-V 添加 Grub 的引导启动方式”。从安装 openEuler、注册 gitee 账号,再到用 QEMU 模拟 RISC-V、学习 Grub,这个比赛让我学到了操作系统启动流程相关的硬核知识,也让我开始了解 openEuler 开源社区。 -带着对openEuler社区的好奇以及对华为公司实习的向往,在2021年1月份,我向负责华为四大开源社区运营的华为计算开源开发与运营部投递了简历。经历了3个月的漫长等待,终于如愿以偿收到了华为实习的Offer,获得了深度参与openEuler社区开发、运营的机会。 +带着对 openEuler 社区的好奇以及对华为公司实习的向往,在2021年1月份,我向负责华为四大开源社区运营的华为计算开源开发与运营部投递了简历。经历了3个月的漫长等待,终于如愿以偿收到了华为实习的 Offer,获得了深度参与 openEuler 社区开发、运营的机会。 -在社区实习几天后,我发现在学校深受大家欢迎的WSL居然还不支持openEuler。WSL即Windows Subsystem for Linux,是 Microsoft 原生的虚拟化方案,能用更快的速度、更少的磁盘,运行各种 Linux发行版,目前主流的Linux发行版都支持: +在社区实习几天后,我发现在学校深受大家欢迎的 WSL 居然还不支持 openEuler。WSL 即 Windows Subsystem for Linux,是 Microsoft 原生的虚拟化方案,能用更快的速度、更少的磁盘,运行各种 Linux 发行版,目前主流的 Linux 发行版都支持。 ![2](https://gitee.com/ouyanghaitao/images/raw/master/2.png) -于是我心想,要不我来补上这块空缺吧。和导师沟通后,导师非常支持我的想法。就这样,我的第一个实习任务就确定了—— 将openEuler发行版移植到Windows WSL。 +于是我心想,要不我来补上这块空缺吧。和导师沟通后,导师非常支持我的想法。就这样,我的第一个实习任务就确定了—— 将 openEuler 发行版移植到 Windows WSL。 ## 提前完成?准备发布? -阅读了WSL相关文档后,我确定Windows WSL可以导入任意的Linux发行版,对于openEuler 而言是没有任何限制的。 +阅读了 WSL 相关文档后,我确定 Windows WSL 可以导入任意的 Linux 发行版,对于 openEuler 而言是没有任何限制的。 -首先是需要一个Linux发行版的根文件系统,使用WSL命令直接将这个文件系统导入即可。为了得到 Linux 发行版的根文件系统,微软建议使用发行版的docker官方镜像,启动容器后使用命令docker export导出容器镜像的快照作为所需的根文件系统。 +首先是需要一个 Linux 发行版的根文件系统,使用 WSL 命令直接将这个文件系统导入即可。为了得到 Linux 发行版的根文件系统,微软建议使用发行版的 docker 官方镜像,启动容器后使用命令 `docker export` 导出容器镜像的快照作为所需的根文件系统。 -在openEuler官网下载板块,我发现每个openEuler发行版都有对应的docker镜像。我下载了[openEuler 20.03 LTS SP1](https://repo.openeuler.org/openEuler-20.03-LTS-SP1/docker_img/x86_64/) 的docker镜像,跟着文档一步一步操作,第二天就在WSL上启动了openEuler。 +在 openEuler 官网下载板块,我发现每个 openEuler 发行版都有对应的 docker 镜像。我下载了 [openEuler 20.03 LTS SP1](https://repo.openeuler.org/openEuler-20.03-LTS-SP1/docker_img/x86_64/) 的 docker 镜像,跟着文档一步一步操作,第二天就在 WSL 上启动了 openEuler。 -满心欢喜的我跟着微软的 WSL 发布文档继续边学习边实践,又用了两三天成功地编译好了安装包。这样在windows下,双击安装包就能安装openEuler 的 WSL 版本。 +满心欢喜的我跟着微软的 WSL 发布文档继续边学习边实践,又用了两三天成功地编译好了安装包。这样在 Windows 下,双击安装包就能安装 openEuler 的 WSL 版本。 -安装包编译完成后,我想把项目代码上传到openEuler社区做存档。这时候我遇到了一个问题:提交代码需要挂靠到某一个SIG下。 +安装包编译完成后,我想把项目代码上传到 openEuler 社区做存档。这时候我遇到了一个问题:提交代码需要挂靠到某一个 SIG 下。 -但是目前并没有WSL相关的SIG,于是我阅读了openEuler官网SIG申请流程,发现如果要成立新的SIG,需要通过社区TC委员会的邮件列表发起申请。于是,我写下了人生第一封开源社区的邮件,向TC委员会提问是否需要创建WSL SIG。很快便收到TC答复,明确不需要新建一个WSL SIG,加入OS-builder SIG即可。后来便参加了OS-builder SIG 双周例会,介绍了当前移植工作以及遇到的问题,并且在OS-builder SIG以及社区帮助下,成功在OS-builder下建立了WSL仓库。 +但是目前并没有 WSL 相关的 SIG,于是我阅读了 openEuler 官网 SIG 申请流程,发现如果要成立新的 SIG,需要通过社区 TC 委员会的邮件列表发起申请。于是,我写下了人生第一封开源社区的邮件,向 TC 委员会提问是否需要创建 WSL SIG。很快便收到 TC 答复,明确不需要新建一个 WSL SIG,加入 OS-builder SIG 即可。后来便参加了 OS-builder SIG 双周例会,介绍了当前移植工作以及遇到的问题,并且在 OS-builder SIG 以及社区帮助下,成功在 OS-builder 下建立了 WSL 仓库。 -中间还有个有趣的小插曲,在社区发邮件期间,民族棋 SIG 的 Maintainer,同时也是为中学生做树莓派科普的袁老师找到我,说看到了我热情洋溢的邮件,问能不能代表同学们采访一下 WSL 项目,说实话当时的我实在是受宠若惊但又内心狂喜。在采访中,首先介绍了openEuler移植到WSL的进展,以及一些Linux入门的知识,其次按照袁老师的建议分享了自己高考考上哈工大(深圳)的经验与心得,同时也分享了多姿多彩的大学生活([采访链接](https://gitee.com/yuandj/siger/blob/master/%E7%AC%AC10%E6%9C%9F%20%E5%8D%97%E5%BE%81%E5%8C%97%E6%88%98%EF%BC%88%E4%B8%8A12%EF%BC%89.md#%E4%B8%80%E5%B0%81%E9%9D%A2%E6%95%85%E4%BA%8B%E9%98%B3%E5%85%89%E6%B5%B7%E6%B6%9B))。 +中间还有个有趣的小插曲,在社区发邮件期间,民族棋 SIG 的 Maintainer,同时也是为中学生做树莓派科普的袁老师找到我,说看到了我热情洋溢的邮件,问能不能代表同学们采访一下 WSL 项目,说实话当时的我实在是受宠若惊但又内心狂喜。在采访中,首先介绍了 openEuler 移植到 WSL 的进展,以及一些 Linux 入门的知识,其次按照袁老师的建议分享了自己高考考上哈工大(深圳)的经验与心得,同时也分享了多姿多彩的大学生活([采访链接](https://gitee.com/yuandj/siger/blob/master/%E7%AC%AC10%E6%9C%9F%20%E5%8D%97%E5%BE%81%E5%8C%97%E6%88%98%EF%BC%88%E4%B8%8A12%EF%BC%89.md#%E4%B8%80%E5%B0%81%E9%9D%A2%E6%95%85%E4%BA%8B%E9%98%B3%E5%85%89%E6%B5%B7%E6%B6%9B))。 -在和导师沟通后我了解到,代码如果要提交到openEuler社区,必须要经过测试。如何测试呢?带着问题,我参与了QA(Quality Assurance)SIG,以及release-management SIG的例会,并在两个SIG的成员建议下,使用了最新的mugen测试框架,搭配integration-test的测试脚本,对移植的系统进行测试。在测试期间,顺便发现了一个测试脚本的bug,修补后提交了PR 。这个bug很简单,就是grep命令与后面的文件名黏在一起了,加个空格隔开就行,但是蚊子腿再小也是肉,第一次找到bug内心还是小有成就滴。 +在和导师沟通后我了解到,代码如果要提交到 openEuler 社区,必须要经过测试。如何测试呢?带着问题,我参与了 QA(Quality Assurance)SIG,以及 release-management SIG 的例会,并在两个 SIG 的成员建议下,使用了最新的 mugen 测试框架,搭配 integration-test 的测试脚本,对移植的系统进行测试。在测试期间,顺便发现了一个测试脚本的 bug,修补后提交了 PR 。这个 bug 很简单,就是 grep 命令与后面的文件名黏在一起了,加个空格隔开就行,但是蚊子腿再小也是肉,第一次找到 bug 内心还是小有成就滴。 -测试结束后,基本操作系统的功能即os-basic文件夹下的测试用例都通过了,不过还有一半的测试用例都没有通过。深入分析报错的log后发现,由于WSL缺少部分原生Linux的功能,导致了很多功能无法开启,相关测试也就无法通过。比如,WSL不支持systemctl,而大部分测试脚本都需要使用systemctl来开启系统功能再进行测试,自然WSL无法通过这些测试,所以测试只好暂时告一段落。虽然这部分测试没有通过,但我使用移植后的openEuler一段时间后没有发现问题,应该不影响正常使用。 +测试结束后,基本操作系统的功能即 os-basic 文件夹下的测试用例都通过了,不过还有一半的测试用例都没有通过。深入分析报错的 log 后发现,由于 WSL 缺少部分原生 Linux 的功能,导致了很多功能无法开启,相关测试也就无法通过。比如,WSL 不支持 systemctl,而大部分测试脚本都需要使用 systemctl 来开启系统功能再进行测试,自然 WSL 无法通过这些测试,所以测试只好暂时告一段落。虽然这部分测试没有通过,但我使用移植后的 openEuler 一段时间后没有发现问题,应该不影响正常使用。 -将测试后的代码提交到wsl仓库,等待PR合入时,我便想同步将安装包提交到Microsoft Store。 +将测试后的代码提交到 wsl 仓库,等待 PR 合入时,我便想同步将安装包提交到 Microsoft Store。 ## 为了发布,寻求帮助 -为了在微软商城发布openEuler的安装包,我需要解决一些技术之外的问题,社区是寻求帮助的最佳途径。 +为了在微软商城发布 openEuler 的安装包,我需要解决一些技术之外的问题,社区是寻求帮助的最佳途径。 -比如,虽然安装包的搞定了,但是安装后在开始菜单显示的logo,效果不如Ubuntu的好。因为openEuler的logo,由蓝色的字母E以及底部的黑色字体openEuler组成。这带来两个问题,一是带文字图标在微软的开始菜单会显得比较小;另一个是我开了windows深色模式,黑色字体在深色背景下根本看不清楚。 +比如,虽然安装包的搞定了,但是安装后在开始菜单显示的 logo,效果不如 Ubuntu 的好。因为 openEuler 的 logo,由蓝色的字母 E 以及底部的黑色字体 openEuler 组成。这带来两个问题,一是带文字图标在微软的开始菜单会显得比较小;另一个是我开了 Windows 深色模式,黑色字体在深色背景下根本看不清楚。 -简单粗暴的解决办法也很好想,我找到logo的矢量图,把字删掉,然后放大就行。但是身边的同事提醒我,去掉文字的logo还有法律效力吗?我能随便去掉一个已注册商标的文字部分,然后拿去发布吗?带着问题,我询问了社区的其他成员,最后辗转找到华为法务部的一位律师姐姐,向她请教logo的法律问题后,她给我了一个商标检索报告截图,告诉我去掉文字的logo也有法律效力。每次想起这个logo,都提醒我在开源社区开发也要注意法务合规。 +简单粗暴的解决办法也很好想,我找到 logo 的矢量图,把字删掉,然后放大就行。但是身边的同事提醒我,去掉文字的 logo 还有法律效力吗?我能随便去掉一个已注册商标的文字部分,然后拿去发布吗?带着问题,我询问了社区的其他成员,最后辗转找到华为法务部的一位律师姐姐,向她请教 logo 的法律问题后,她给我了一个商标检索报告截图,告诉我去掉文字的 logo 也有法律效力。每次想起这个 logo,都提醒我在开源社区开发也要注意法务合规。 -解决了Logo问题后,便可以准备提交到微软商城了。WSL文档里提到,如果要发布,需要写邮件给WSL团队,经过他们的测试后,才能发布,于是我便第一时间写了一封英文邮件给WSL团队。 +解决了 Logo 问题后,便可以准备提交到微软商城了。WSL 文档里提到,如果要发布,需要写邮件给 WSL 团队,经过他们的测试后,才能发布,于是我便第一时间写了一封英文邮件给 WSL 团队。 -等了两个星期,WSL团队没有回复。我只好再发一封邮件,运气不错的是,这次等了几天后,WSL团队终于回复我了,说前段时间正处于微软一年中专门开会的月份,很忙,所以没看到邮件。并且表示,WSL移植好后可以直接提交,无需测试。 +等了两个星期,WSL 团队没有回复。我只好再发一封邮件,运气不错的是,这次等了几天后,WSL 团队终于回复我了,说前段时间正处于微软一年中专门开会的月份,很忙,所以没看到邮件。并且表示,WSL 移植好后可以直接提交,无需测试。 -文档里说,如果要将软件安装包发布到微软商城,需要注册一个微软合作中心账户,这个账户分公司账户和个人账户。前者需要提交创办公司的官方证明文件,微软审核通过后才能发布软件,后者则无需微软审核。在公司与个人账户的选择之间,我想先试试能不能创建公司账号。虽然openEuler不是公司,只是一个社区,但是毕竟公司账号能支持更多人登录,且能发布特定功能的APP,权限更高。于是我在社区,找到了社区基础设施SIG的Maintainer,在他的帮助下,使用了openEuler的一个公共邮箱注册微软账号。在验证完邮箱后,微软合作中心提示,employment verification失败,需要提供openeuler.io这个域名是由我们注册的证明。于是我又向社区基础设施SIG要证明材料,得到几个管理员界面的截图后,按照微软文档里面的说明提交了材料,又开始了新的漫长的等待。 +文档里说,如果要将软件安装包发布到微软商城,需要注册一个微软合作中心账户,这个账户分公司账户和个人账户。前者需要提交创办公司的官方证明文件,微软审核通过后才能发布软件,后者则无需微软审核。在公司与个人账户的选择之间,我想先试试能不能创建公司账号。虽然 openEuler 不是公司,只是一个社区,但是毕竟公司账号能支持更多人登录,且能发布特定功能的 APP,权限更高。于是我在社区,找到了社区基础设施 SIG 的 Maintainer,在他的帮助下,使用了 openEuler 的一个公共邮箱注册微软账号。在验证完邮箱后,微软合作中心提示,employment verification 失败,需要提供 openeuler.io 这个域名是由我们注册的证明。于是我又向社区基础设施 SIG 要证明材料,得到几个管理员界面的截图后,按照微软文档里面的说明提交了材料,又开始了新的漫长的等待。 -又是两周,微软还是没有回复。在微软合作中心的论坛中,发现有几个人卡在了相同的验证阶段,他们发帖称自己按照文档提交了证明材料后,微软拖了很久都没回应,短的几个星期,慢的几个月。但在他们发帖表示微软拖延后,都有微软的管理员立即跟进,人工帮助他们解决了验证问题。学到这招后我便在讨论区提交了support,希望有客服也来帮助我通过验证。 +又是两周,微软还是没有回复。在微软合作中心的论坛中,发现有几个人卡在了相同的验证阶段,他们发帖称自己按照文档提交了证明材料后,微软拖了很久都没回应,短的几个星期,慢的几个月。但在他们发帖表示微软拖延后,都有微软的管理员立即跟进,人工帮助他们解决了验证问题。学到这招后我便在讨论区提交了 support,希望有客服也来帮助我通过验证。 几天后,果然有从美国打来的电话与我沟通。但是我们讨论了一下午,她都没有解决我的问题。后来发现,我问题分类找错了,原因是与账号相关的问题有好几个,彼此之间都很相似。 @@ -67,23 +67,23 @@ permalink: /story/wanghaitao ## 喜提发布,收获满满 -人工客服无法解决我的问题,我只好继续等待我的证明材料能被微软工作人员处理。运气不错的是,过了一个星期左右,微软发邮件告诉我,除了截图以外,要提供创办公司的PDF官方证明,可是openEuler是一个开源社区而不是商业公司,没有官方证明。于是经过openEuler 社区的讨论,我们决定先用个人账户发布。 +人工客服无法解决我的问题,我只好继续等待我的证明材料能被微软工作人员处理。运气不错的是,过了一个星期左右,微软发邮件告诉我,除了截图以外,要提供创办公司的 PDF 官方证明,可是 openEuler 是一个开源社区而不是商业公司,没有官方证明。于是经过 openEuler 社区的讨论,我们决定先用个人账户发布。 -这次使用另一个openEuler的邮箱来创建了一个微软的个人账户,由于不需要繁琐的验证,我很顺利地,提交了应用上传的所需信息。但是发布时,我却怎么也无法提交安装包,一直提示错签名不对。在翻看YouTube上微软发布软件的介绍,以及在Stack Overflow上搜索相应问题时,我发现签名需要提供开发者账号的Windows publisher ID,即CN开头的一串号码。使用这个号码来作为Visual Studio签名安装包的Publisher common name,签名后的安装包能正确被微软合作中心成功识别,于是我便成功将安装包提交到了微软合作伙伴中心。而这一点,我翻遍了微软开发文档都没找到相关提醒。 +这次使用另一个 openEuler 的邮箱来创建了一个微软的个人账户,由于不需要繁琐的验证,我很顺利地,提交了应用上传的所需信息。但是发布时,我却怎么也无法提交安装包,一直提示错签名不对。在翻看 YouTube 上微软发布软件的介绍,以及在 Stack Overflow 上搜索相应问题时,我发现签名需要提供开发者账号的 Windows publisher ID,即 CN 开头的一串号码。使用这个号码来作为 Visual Studio 签名安装包的 Publisher common name,签名后的安装包能正确被微软合作中心成功识别,于是我便成功将安装包提交到了微软合作伙伴中心。而这一点,我翻遍了微软开发文档都没找到相关提醒。 -让人意外的是,这次没有等几个星期,而是在三天后我就收到了微软的修改建议。我按照微软要求,修改privacy链接,加上openEuler不支持Windows 10 S申明后,重新提交了应用上传请求,本以为仍需要等待一段时间才能发布,没想到数日后,商城居然可以搜到openEuler !发布成功了! +让人意外的是,这次没有等几个星期,而是在三天后我就收到了微软的修改建议。我按照微软要求,修改 privacy 链接,加上 openEuler 不支持 Windows 10 S 申明后,重新提交了应用上传请求,本以为仍需要等待一段时间才能发布,没想到数日后,商城居然可以搜到 openEuler!发布成功了! ![3](https://gitee.com/ouyanghaitao/images/raw/master/3.png) -上面是 openEuler 在 Microsoft Store 的截图,感兴趣的朋友可以通过[链接1](https://www.microsoft.com/zh-cn/p/openeuler/9ngf0q0xp03d?rtc=1&activetab=pivot:overviewtab)来安装。需要注意的是,在安装WSL 任何发行版之前,需要先启用 WSL 这个功能,具体可以参考[链接2](https://gitee.com/openeuler/wsl)。 +上面是 openEuler 在 Microsoft Store 的截图,感兴趣的朋友可以通过[链接1](https://www.microsoft.com/zh-cn/p/openeuler/9ngf0q0xp03d?rtc=1&activetab=pivot:overviewtab)来安装。需要注意的是,在安装 WSL 任何发行版之前,需要先启用 WSL 这个功能,具体可以参考[链接2](https://gitee.com/openeuler/wsl)。 -三个月的工作终于是告一段落了。在这期间,我写下了人生第一封英文邮件给微软,写下了第一封给开源社区的邮件,第一次与社区成员沟通讨论openEuler,在这个过程中,我感觉自己已经融入到了openEuler这个大家庭中。 +三个月的工作终于是告一段落了。在这期间,我写下了人生第一封英文邮件给微软,写下了第一封给开源社区的邮件,第一次与社区成员沟通讨论 openEuler,在这个过程中,我感觉自己已经融入到了 openEuler 这个大家庭中。 -同时在华为实习工作中,工作氛围很好,同事之间互助友爱。于是我决定延长实习,从原计划7月结束实习,延长到9月底结束。希望在后续的三个月实习时间里,我能学到更多,也能为openEuler做更多贡献! +同时在华为实习工作中,工作氛围很好,同事之间互助友爱。于是我决定延长实习,从原计划7月结束实习,延长到9月底结束。希望在后续的三个月实习时间里,我能学到更多,也能为 openEuler 做更多贡献! -最后附上我总结的关于移植openEuler到WSL的技术文档,里面介绍了如何在WSL里安装openEuler,以及移植的过程: -https://gitee.com/openeuler/wsl 。如果有任何问题,欢迎在openEuler社区wsl仓库提 Issue,https://gitee.com/openeuler/wsl/issues 。 +最后附上我总结的关于移植 openEuler 到 WSL 的技术文档,里面介绍了如何在 WSL 里安装 openEuler,以及移植的过程:[https://gitee.com/openeuler/wsl](https://gitee.com/openeuler/wsl)。如果有任何问题,欢迎在 openEuler 社区 wsl 仓库提 Issue,[https://gitee.com/openeuler/wsl/issues](https://gitee.com/openeuler/wsl/issues)。 如果你想参与 openEuler 开发,可以搜索微信小程序 “openEuler”,里面有 80 多个 SIG 例会时间、议题以及 openEuler 的线上和线下的 Meetup 。你可以选择你感兴趣议题参与例会,在会议中和社区成员进行详细的沟通,也可以到现场来参与 Meetup 活动。 -欢迎为 openEuler 社区添砖加瓦! \ No newline at end of file +欢迎为 openEuler 社区添砖加瓦! + diff --git "a/src/story/stories/\346\204\237\350\260\242Apache DolphinScheduler\357\274\214\350\256\251\346\210\221\347\232\204\351\235\222\346\230\245\346\260\270\344\270\215\350\244\252\350\211\262.md" "b/src/story/stories/\346\204\237\350\260\242Apache DolphinScheduler\357\274\214\350\256\251\346\210\221\347\232\204\351\235\222\346\230\245\346\260\270\344\270\215\350\244\252\350\211\262.md" index b5eb6dc1d9aa35e9291b62472c4e6e226f8cadb8..2ef860979b2bc7bf5252732613e04a49e9fc0594 100644 --- "a/src/story/stories/\346\204\237\350\260\242Apache DolphinScheduler\357\274\214\350\256\251\346\210\221\347\232\204\351\235\222\346\230\245\346\260\270\344\270\215\350\244\252\350\211\262.md" +++ "b/src/story/stories/\346\204\237\350\260\242Apache DolphinScheduler\357\274\214\350\256\251\346\210\221\347\232\204\351\235\222\346\230\245\346\260\270\344\270\215\350\244\252\350\211\262.md" @@ -1,86 +1,85 @@ ---- -title: 感谢Apache DolphinScheduler,让我的青春永不褪色 -author: 李岗 -date: 2021-01-21 -permalink: /story/ligang ---- - -## 个人介绍 - -我是李岗,是一名开源的爱好者和实践者,是Apache DolphinScheduler(incubator)的初始提交者和PPMC,也是Apache Local Community Beijing(ALC-Beijing)的member。 - -很开心、很庆幸自己可以成为开源领域的一员,更希望自己在未来不断地对开源持续探索、持续实践、持续分享,最终在开源领域贡献出自己的力量。 - -## 心路历程 - -一篇暴击心灵的文章、一场震撼人心的演讲都有可能成功让我们对开源产生好奇,产生兴趣,甚至一见钟情; - -另一方面,开源软件也在不断地改变我们的生活和工作,每一次开源软件的使用都可能让我惊叹开源软件的魅力,不知不觉我们就已经种下了一颗希望的种子,希望自己有一天也可以进入到开源领域,希望自己写的代码,做出的贡献可以影响到全世界更多的人。 - -当这些充满希望、充满梦想的种子在我们心中开始发芽的时候,总有一天他会呼唤着我们行动起来,加入到开源领域。 - -与很多开源爱好者相比,我是幸运的,在2017年的时候,为了更好地支撑易观千帆产品,公司需要自研一个分布式的任务调度系统来调度自身的任务,而易观的企业文化就是独立、勇敢、乐观、开放,那我们就决定做一个开源的系统,把代码开放出去,让更多的企业去使用,自此我就开始了自己的开源之旅。 - -万丈高楼平地起,从项目启动的那一刻,我们就确定了开源的目标,也从那一刻,开源的种子也种在了每个人的心中,它是一个使命,也是所有人的共识和承诺。 - -分秒必争,使命必达,所有人都整装待发,2019年3月,我们迎来了第一批的外部种子用户,正式发布第一个开源版本1.0.0。后续又逐步推出了1.0.1,1.0.2,1.0.3版本。 - -开源的种子已经种下,只有破土而出,才能扎根于大地,我们又开始了新的征程,我们要进入到全球最大的基金会,也就是Apache基金会。 - -目标是坚定地,征程却是充满了挑战,所幸最终我们始终坚持,迎来了曙光,迎来了2019年8月29日DolphinScheduler成功过入到Apache孵化器的消息。当看到邮件里不断地出现+1,+1,+1的时候,一切的付出都变为了收获,一切的汗水都化为了成长。 - - ## 开源能力 - -如果自己进入到开源领域是幸运的,那么当我首次从吴晟老师那里听到Apache Way的理念时,我一直在为Apache之道惊叹不已,我希望自己在未来可以去探索,去实践。 - -进入到Apache孵化器后,第一个里程碑就是要发布Apache Release,我自告奋勇充当了第一次的Release Manager,对于我印象最深的就是进行license的合规检查: - -“什么是二进制依赖和源码依赖,如何根据二进制依赖和源码依赖列出license?” - -“如何添加源码依赖?哪些license可以用于源码依赖?” - -“前端字体和图标是否符合license许可?” - -.......... - -因为Apache有着完善的法律框架和社会治理框架,对于license和商标有着近乎严苛的要求,在release的时候会进行非常仔细地检查,一开始真的没有太多的概念,而这些又特别的重要,否则就无法发版出来。我们的第一次发版就用了将近4个月的时间。 - -这里可以放一个链接(https://apache.org/legal/resolved.html#highlevel),如果大家之前也没有接触过,可以看一下,我想就可以体会出我当时的心情。 - -经历过第一次Apache Release,自己也更加体会到了Apache之道的独特魅力,精英治理、社区驱动、共识决策、透明开放都深深的吸引着我,也正是这种吸引让我继续前行。 - -2020年2月,当我在apache community的dev邮件列表里看到ALC Beijing要成立的消息时, - -就开始回想自己的apache之路,有迷茫、有困惑、有挑战、有喜悦,它既是一段充满挑战的修行,也是一段浪漫的开源之旅。ALC Beijing的成立点燃了我内心的另外一盏灯,自己不仅仅是要做apache开源软件的参与者和贡献者,也希望可以成为一名Apache开源文化传播者。自己也特别有幸可以成为ALC Beijing的成员,在这里也收获了很多,因为在这里有很多的开源前辈,并且他们都非常热心,我们在2020的年终会议上也坚定了使命:帮助更多国内优秀的开源项目进入到Apache基金会,我们要让国内更多的项目走出去,走向全世界。 - -## 开源分享 - -Apache基金会是一个大家庭,非常的平等,非常的包容,我也希望可以把自己对开源的体会分享出去,传递给更多希望进入到开源的爱好者,在这里特别让我感触的是,我在南京开源供应链峰会开源-教育分论坛上进行的一次分享,我对教育有一种特别的情结,教育是伟大而神圣的事业,教育是为天地立心,为生民立命,为往圣继绝学,为万世开太平。我仿佛看到了冥冥之中的那一丝牵引,教育,开源,两个让我魂牵梦绕,荡气回肠的梦想,让我找到了一种新的责任,新的使命。 - -2020年自己也参与到了Outreachy活动,成为了一名mentor,我会与远在海外的实习生异步沟通,我们在slack交流,在邮件列表交流,我希望在这个短暂的实习旅途里他们不仅仅可以提升代码技能,也可以体会到开源异步协作,积累开源沟通技巧! - -教育,开源这两个响亮的名字再一次响彻我的心中,我推开窗户,抬头望了一下蔚蓝的天空,眼睛盯着蔚蓝天空的白云深处,我想我已经找到了让我飞翔和驰骋的地方。 - -## 开源总结 - -参与到开源项目是很好的去提升自己技术和架构能力的途径,因为Apache的开源项目都是公开透明的,在这里不仅是代码公开透明,技术方案讨论、决策也都是公开透明的,我们都可以从github的issue和邮件列表里看到。所以只要我们持续的参与开源项目,无论是从技术广度和深度都会与不错的提升。 - -除去技术,更多的是在社区里如何讨论,如何决策,因为这里遵循着共识的机制,能不投票就不要投票,所以我们会发现很多时候对于方案的推进会相对较慢,但是它的优势是方案的讨论会更加的全面,这里其实就相当于Peer Review,我们都在通过邮件去表达想法,它一定是更加的全面和优质的,那么共识其实就是在这里找到一个平衡,从而更加稳定的去推动项目健康的向前发展。 - -因为社区的本质是人,好的代码,好的架构,好的文档都是由每一位贡献者完成的,我们在通过协作的模式去改变着这个community. - -感谢易观,感谢CTO郭炜老师,让我可以幸运的成为一名全职的开源工程师。 - -感谢我们的导师吴晟老师、史少锋老师、陈亮老师、Furkan Kamaci老师和Kevin Ratnasekera老师,感谢导师们对我们的耐心指导和每一次Apache Release的细心检查。 - -感谢每一位使用过DS的用户、每一位参与过DS社区贡献的伙伴,感谢你们愿意牺牲自己宝贵的时间与我们一同前行!感谢姜宁老师、李建盛老师、孙金城老师和娟神以及所有指导和帮助过我的各位开源大咖和贡献者。 - -太多的感谢汇成一句话,感谢所有的开源爱好者组成了一个平等、开放、精英、共识的大家庭,可以让我们一起修行、一起成长、让我们在忙碌之余依然有着诗和远方。 - -## 共同期许 - -坚持自己的理想,追逐自己的梦想,并且探索自己独立的思想的时候,我们的青春就已经开始了,希望你与开源的遇见是青春的开始,或者是青春的延续! - -我特别喜欢关于教育的一句话,教育是一棵树摇动着一棵树,一个灵魂感动着一个灵魂,其实开源也是如此,当我们作为新手时,社区会给我们提供很多帮助,而当我们不断地贡献,我们会获取到社区的信任,然后自己有了影响力,我们又开始去帮助更多的新加入开源的爱好者,这其实也是在不断地传递开源精神,传播知识和技能。 - -我也真心祝愿我们所有的开源爱好者都可以通过开源创造出一个属于自己的故事,这个故事关于独立、关于开放、关于挑战,我们选择了做一名斗士,挑战全新的异步协作模式、挑战自己的英语、挑战自己的演讲、挑战自己的写作,甚至我们会把开源当作一辈子的职业,我相信再过了5年,10年,我们一定感谢那个曾经的自己,当我们慕然回首,一定会对当初的那个自己说一句:"谢谢你,我的开源,我的青春!" +--- +title: 感谢 Apache DolphinScheduler,让我的青春永不褪色 +author: 李岗 +date: 2021-01-21 +permalink: /story/ligang +--- + +## 个人介绍 + +我是李岗,是一名开源的爱好者和实践者,是 Apache DolphinScheduler(incubator)的初始提交者和 PPMC,也是 Apache Local Community Beijing(ALC-Beijing)的 member。 + +很开心、很庆幸自己可以成为开源领域的一员,更希望自己在未来不断地对开源持续探索、持续实践、持续分享,最终在开源领域贡献出自己的力量。 + +## 心路历程 + +一篇暴击心灵的文章、一场震撼人心的演讲都有可能成功让我们对开源产生好奇,产生兴趣,甚至一见钟情。 + +另一方面,开源软件也在不断地改变我们的生活和工作,每一次开源软件的使用都可能让我惊叹开源软件的魅力,不知不觉我们就已经种下了一颗希望的种子,希望自己有一天也可以进入到开源领域,希望自己写的代码,做出的贡献可以影响到全世界更多的人。 + +当这些充满希望、充满梦想的种子在我们心中开始发芽的时候,总有一天他会呼唤着我们行动起来,加入到开源领域。 + +与很多开源爱好者相比,我是幸运的,在2017年的时候,为了更好地支撑易观千帆产品,公司需要自研一个分布式的任务调度系统来调度自身的任务,而易观的企业文化就是独立、勇敢、乐观、开放,那我们就决定做一个开源的系统,把代码开放出去,让更多的企业去使用,自此我就开始了自己的开源之旅。 + +万丈高楼平地起,从项目启动的那一刻,我们就确定了开源的目标,也从那一刻,开源的种子也种在了每个人的心中,它是一个使命,也是所有人的共识和承诺。 + +分秒必争,使命必达,所有人都整装待发,2019年3月,我们迎来了第一批的外部种子用户,正式发布第一个开源版本 1.0.0。后续又逐步推出了 1.0.1、1.0.2、1.0.3 版本。 + +开源的种子已经种下,只有破土而出,才能扎根于大地,我们又开始了新的征程,我们要进入到全球最大的基金会,也就是 Apache 基金会。 + +目标是坚定地,征程却是充满了挑战,所幸最终我们始终坚持,迎来了曙光,迎来了2019年8月29日 DolphinScheduler 成功过入到 Apache 孵化器的消息。当看到邮件里不断地出现 +1,+1,+1 的时候,一切的付出都变为了收获,一切的汗水都化为了成长。 + + ## 开源能力 + +如果自己进入到开源领域是幸运的,那么当我首次从吴晟老师那里听到 Apache Way 的理念时,我一直在为 Apache 之道惊叹不已,我希望自己在未来可以去探索,去实践。 + +进入到 Apache 孵化器后,第一个里程碑就是要发布 Apache Release,我自告奋勇充当了第一次的 Release Manager,对于我印象最深的就是进行 license 的合规检查: + +“什么是二进制依赖和源码依赖,如何根据二进制依赖和源码依赖列出 license?” + +“如何添加源码依赖?哪些 license 可以用于源码依赖?” + +“前端字体和图标是否符合 license 许可?” + +.......... + +因为 Apache 有着完善的法律框架和社会治理框架,对于 license 和商标有着近乎严苛的要求,在 release 的时候会进行非常仔细地检查,一开始真的没有太多的概念,而这些又特别的重要,否则就无法发版出来。我们的第一次发版就用了将近4个月的时间。 + +这里可以放一个[链接](https://apache.org/legal/resolved.html#highlevel),如果大家之前也没有接触过,可以看一下,我想就可以体会出我当时的心情。 + +经历过第一次 Apache Release,自己也更加体会到了 Apache 之道的独特魅力,精英治理、社区驱动、共识决策、透明开放都深深的吸引着我,也正是这种吸引让我继续前行。 + +2020年2月,当我在 Apache community 的 dev 邮件列表里看到 ALC Beijing 要成立的消息时,就开始回想自己的 Apache 之路,有迷茫、有困惑、有挑战、有喜悦,它既是一段充满挑战的修行,也是一段浪漫的开源之旅。ALC Beijing的成立点燃了我内心的另外一盏灯,自己不仅仅是要做 Apache 开源软件的参与者和贡献者,也希望可以成为一名 Apache 开源文化传播者。自己也特别有幸可以成为 ALC Beijing 的成员,在这里也收获了很多,因为在这里有很多的开源前辈,并且他们都非常热心,我们在2020的年终会议上也坚定了使命 —— 帮助更多国内优秀的开源项目进入到 Apache 基金会,我们要让国内更多的项目走出去,走向全世界。 + +## 开源分享 + +Apache 基金会是一个大家庭,非常的平等,非常的包容,我也希望可以把自己对开源的体会分享出去,传递给更多希望进入到开源的爱好者,在这里特别让我感触的是,我在南京开源供应链峰会开源-教育分论坛上进行的一次分享,我对教育有一种特别的情结,教育是伟大而神圣的事业,教育是为天地立心,为生民立命,为往圣继绝学,为万世开太平。我仿佛看到了冥冥之中的那一丝牵引,教育、开源,两个让我魂牵梦绕,荡气回肠的梦想,让我找到了一种新的责任,新的使命。 + +2020年自己也参与到了 Outreachy 活动,成为了一名 mentor,我会与远在海外的实习生异步沟通,我们在 slack 交流,在邮件列表交流,我希望在这个短暂的实习旅途里他们不仅仅可以提升代码技能,也可以体会到开源异步协作,积累开源沟通技巧! + +“教育、开源” 这两个响亮的名字再一次响彻我的心中,我推开窗户,抬头望了一下蔚蓝的天空,眼睛盯着蔚蓝天空的白云深处,我想我已经找到了让我飞翔和驰骋的地方。 + +## 开源总结 + +参与到开源项目是很好的去提升自己技术和架构能力的途径,因为 Apache 的开源项目都是公开透明的,在这里不仅是代码公开透明,技术方案讨论、决策也都是公开透明的,我们都可以从 GitHub 的 issue 和邮件列表里看到。所以只要我们持续的参与开源项目,无论是从技术广度和深度都会与不错的提升。 + +除去技术,更多的是在社区里如何讨论、如何决策,因为这里遵循着共识的机制,能不投票就不要投票,所以我们会发现很多时候对于方案的推进会相对较慢,但是它的优势是方案的讨论会更加的全面,这里其实就相当于 Peer Review,我们都在通过邮件去表达想法,它一定是更加的全面和优质的,那么共识其实就是在这里找到一个平衡,从而更加稳定的去推动项目健康的向前发展。 + +因为社区的本质是人,好的代码、好的架构、好的文档都是由每一位贡献者完成的,我们在通过协作的模式去改变着这个 community。 + +感谢易观,感谢 CTO 郭炜老师,让我可以幸运的成为一名全职的开源工程师。 + +感谢我们的导师吴晟老师、史少锋老师、陈亮老师、Furkan Kamaci 老师和 Kevin Ratnasekera 老师,感谢导师们对我们的耐心指导和每一次 Apache Release 的细心检查。 + +感谢每一位使用过 DS 的用户、每一位参与过 DS 社区贡献的伙伴,感谢你们愿意牺牲自己宝贵的时间与我们一同前行!感谢姜宁老师、李建盛老师、孙金城老师和娟神以及所有指导和帮助过我的各位开源大咖和贡献者。 + +太多的感谢汇成一句话,感谢所有的开源爱好者组成了一个平等、开放、精英、共识的大家庭,可以让我们一起修行、一起成长、让我们在忙碌之余依然有着诗和远方。 + +## 共同期许 + +坚持自己的理想,追逐自己的梦想,并且探索自己独立的思想的时候,我们的青春就已经开始了,希望你与开源的遇见是青春的开始,或者是青春的延续! + +我特别喜欢关于教育的一句话,教育是一棵树摇动着一棵树,一个灵魂感动着一个灵魂,其实开源也是如此,当我们作为新手时,社区会给我们提供很多帮助,而当我们不断地贡献,我们会获取到社区的信任,然后自己有了影响力,我们又开始去帮助更多的新加入开源的爱好者,这其实也是在不断地传递开源精神,传播知识和技能。 + +我也真心祝愿我们所有的开源爱好者都可以通过开源创造出一个属于自己的故事,这个故事关于独立、关于开放、关于挑战,我们选择了做一名斗士,挑战全新的异步协作模式、挑战自己的英语、挑战自己的演讲、挑战自己的写作,甚至我们会把开源当作一辈子的职业,我相信再过了5年、10年,我们一定感谢那个曾经的自己,当我们慕然回首,一定会对当初的那个自己说一句:“谢谢你,我的开源,我的青春!” + diff --git "a/src/story/stories/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JAP\347\232\204\346\225\205\344\272\213.md" "b/src/story/stories/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JAP\347\232\204\346\225\205\344\272\213.md" new file mode 100644 index 0000000000000000000000000000000000000000..724cfad0048f65242e59d20cb806ebfb5078de12 --- /dev/null +++ "b/src/story/stories/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JAP\347\232\204\346\225\205\344\272\213.md" @@ -0,0 +1,36 @@ +--- +title: 要懂得舍得的 UMS 与 JAP 的故事 +author: 要懂得舍得 +date: 2021-01-29 +permalink: /story/pcore +--- + +## 为什么决定参与贡献 + +1. 2020 注定是不平凡的一年, 疫情让我有更多的空余时间; +2. 为了给自己身上增加一点光环; +3. 平时每次做新项目项目都需要搞一套用户管理系统, 虽然可以搬砖, 但也繁琐, 想着正好有空, 何不自己写一套用户管理脚手架, 省的以后搬砖; 就这样有了我的开源项目 [UMS](https://gitee.com/pcore/UMS )。 + +### 项目1:[UMS](https://gitee.com/pcore/UMS ) + +用户管理脚手架集成:用户密码登录、手机登录、支持所有 JustAuth 支持的第三方授权登录、验证码、基于 RBAC 的访问权限控制功能, 支持多租户、JWT、SLF4J-MDC、签到等功能。 + +你只需要实现业务端的几个接口 **用户服务, 短信发送服务, 获取角色权限服务, JWT(可以配置是否开启)服务** 几个 API 接口就可以实现上述功能。 + +可通过属性配置高度自定义,UMS 是非侵入式的,与业务高度解耦;只需要专注于自己的业务逻辑。 + +### 项目2:[JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) + +Spring security 与 JustAuth 集成:支持所有 justAuth 支持的第三方登录,[JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 项目已加入 [JustAuth](https://gitee.com/justauth ) 大家庭。 + +## 参与后的收获或提升 + +参与开源后认识了很多小伙伴,有参与 [UMS](https://gitee.com/pcore/UMS ) 和 [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 开源的,有使用 [UMS](https://gitee.com/pcore/UMS ) 和 [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 的小伙伴,以及加入了 [JustAuth](https://gitee.com/justauth ) 这个大家庭。 + +开源表面上看只有付出没有回报,其实通过开源潜移默化的会提升自己的技术与视野,还有机会与朋友圈,本人也因为 [UMS](https://gitee.com/pcore/UMS) 项目认识了一个小伙伴,加入了他的创业公司。说了这么多就一句话:我为人人,人人为我。 + +## 如何接触/了解到这个开源项目 + +通过第二个项目 [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 认识了 **GVP** 项目 [JustAuth](https://gitee.com/justauth ) 的作者,也加入 [JustAuth](https://gitee.com/justauth ) 大家庭,[JustAuth](https://gitee.com/justauth ) 作者今天刚推出了新的开源项目 [JAP](https://gitee.com/fujieid/jap)(全称 JustAuthPlus),我也成为其中的一员, 希望 2021 年 [JAP](https://gitee.com/fujieid/jap) 成为又一个 **GVP** 项目。 + +**2021 加油!** diff --git "a/src/story/stories/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JPA\347\232\204\346\225\205\344\272\213.md" "b/src/story/stories/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JPA\347\232\204\346\225\205\344\272\213.md" deleted file mode 100644 index 2ae0618a2c6bbddf2bc82154b3ff84e641aa3f06..0000000000000000000000000000000000000000 --- "a/src/story/stories/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JPA\347\232\204\346\225\205\344\272\213.md" +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: 要懂得舍得的UMS与JPA的故事 -author: 要懂得舍得 -date: 2021-01-29 -permalink: /story/pcore ---- - -## 为什么决定参与贡献 - -1. 2020 注定是不平凡的一年, 疫情让我有更多的空余时间; -2. 为了给自己身上增加一点光环; -3. 平时每次做新项目项目都需要搞一套用户管理系统, 虽然可以搬砖, 但也繁琐, 想着正好有空, 何不自己写一套用户管理脚手架, 省的以后搬砖; 就这样有了我的开源项目[UMS](https://gitee.com/pcore/UMS )。 - -### 项目1: [UMS](https://gitee.com/pcore/UMS ) 项目: https://gitee.com/pcore/UMS - -用户管理脚手架集成:用户密码登录、手机登录、支持所有 JustAuth 支持的第三方授权登录、验证码、基于 RBAC 的访问权限控制功能, 支持多租户、JWT、SLF4J-MDC、签到等功能。 - -你只需要实现业务端的几个接口 **用户服务, 短信发送服务, 获取角色权限服务, JWT(可以配置是否开启)服务** 几个 API 接口就可以实现上述功能。 - -可通过属性配置高度自定义, UMS 是非侵入式的, 与业务高度解耦; 只需要专注于自己的业务逻辑。 - -### 项目2: [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 项目: https://gitee.com/pcore/just-auth-spring-security-starter - -Spring security 与 JustAuth 集成: 支持所有 justAuth 支持的第三方登录,[JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 项目已加入 [JustAuth](https://gitee.com/justauth ) 大家庭。 - -## 参与后的收获或提升 - -参与开源后认识了很多小伙伴, 有参与 [UMS](https://gitee.com/pcore/UMS ) 和 [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 开源的,有使用 [UMS](https://gitee.com/pcore/UMS ) 和 [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 的小伙伴,以及加入了 [JustAuth](https://gitee.com/justauth ) 这个大家庭。 - -开源表面上看只有付出没有回报, 其实通过开源潜移默化的会提升自己的技术与视野, 还有机会与朋友圈, 本人也因为 [UMS](https://gitee.com/pcore/UMS) 项目认识了一个小伙伴, 加入了他的创业公司. 说了这么多就一句话: 我为人人, 人人为我。 - -## 如何接触/了解到这个开源项目 - -通过第二个项目[JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 认识了 **GVP** 项目 [JustAuth](https://gitee.com/justauth ) 的作者, 也加入 [JustAuth](https://gitee.com/justauth ) 大家庭, [JustAuth](https://gitee.com/justauth ) 作者今天刚推出了新的开源项目 [JPA](https://gitee.com/fujieid/jap) 我也成为其中的一员, 希望 2021 年 [JPA](https://gitee.com/fujieid/jap) 成为又一个 **GVP** 项目。 - -**2021 加油!** diff --git "a/src/story/stories/\350\275\273\347\274\226\347\250\213\344\270\216CRMEB\346\211\223\351\200\232\347\211\210\347\232\204\346\225\205\344\272\213.md" "b/src/story/stories/\350\275\273\347\274\226\347\250\213\344\270\216CRMEB\346\211\223\351\200\232\347\211\210\347\232\204\346\225\205\344\272\213.md" index 3138bd48fb47bb278e783d52ee14f449db802324..34637cfe29d0e182ae75104b070c8657605a83ba 100644 --- "a/src/story/stories/\350\275\273\347\274\226\347\250\213\344\270\216CRMEB\346\211\223\351\200\232\347\211\210\347\232\204\346\225\205\344\272\213.md" +++ "b/src/story/stories/\350\275\273\347\274\226\347\250\213\344\270\216CRMEB\346\211\223\351\200\232\347\211\210\347\232\204\346\225\205\344\272\213.md" @@ -1,14 +1,15 @@ ---- -title: 轻编程与CRMEB打通版的故事 -author: 轻编程 -date: 2021-01-20 -permalink: /story/qbiancheng ---- - -第一次听CRMEB这个名字还是一个朋友说用这个开源仓库为客户定制二开了一个项目,赚了多少多少钱,这多少让我有些嫉妒。 - -刚听到这个名字时十分好奇,是CRM客户关系管理系统吗?但为什么小程序商城可以用这个来定制开发?怀着这样的一个好奇心,去搜索引擎搜索,去Gitee搜索开源项目,一看Star量已达5k之高,再看代码质量以及UI设计确实做的非常棒,看官方的简介是将客户关系管理与社交电商营销系统深度集成的一款开源系统,打通了H5端和小程序端数据互通的问题,确实很有吸引力! - -基于这样的一个机遇,自己手里的一些商业项目也转型用到了这个开源仓库,在使用过程中也遇到一些小的bug,在帮客户解决这些bug的时候就顺手将处理的代码提交给了开源作者,惊喜的是作者竟然真的收录我提交的代码,这让我收获了满满的成就感,本来个人的技术是偏于后端PHP的,对前后端分离技术实践较少,但庆幸的是这套开源系统是基于前后端分离开发,在使用过程中多少是有一些障碍,正是因为这些障碍,让我不断的学习新技术,去了解前端非常优秀的vuejs框架,自己在前端技术上有了质的提升,这套系统确实减少了我重复造轮子的工作量,也让我学习了很多! - -开源是一件非常有意义的事情,正因为这个开源项目给了我很大的启发,我自己也在着手开发一个开源项目,希望把自己多年来积累的经验融入到这个开源项目,帮助更多人,也满足了自己在技术世界遨游的小梦想! \ No newline at end of file +--- +title: 轻编程与 CRMEB 打通版的故事 +author: 轻编程 +date: 2021-01-20 +permalink: /story/qbiancheng +--- + +第一次听 CRMEB 这个名字还是一个朋友说用这个开源仓库为客户定制二开了一个项目,赚了多少多少钱,这多少让我有些嫉妒。 + +刚听到这个名字时十分好奇,是 CRM 客户关系管理系统吗?但为什么小程序商城可以用这个来定制开发?怀着这样的一个好奇心,去搜索引擎搜索,去 Gitee 搜索开源项目,一看 Star 量已达 5k 之高,再看代码质量以及 UI 设计确实做的非常棒,看官方的简介是将客户关系管理与社交电商营销系统深度集成的一款开源系统,打通了 H5 端和小程序端数据互通的问题,确实很有吸引力! + +基于这样的一个机遇,自己手里的一些商业项目也转型用到了这个开源仓库,在使用过程中也遇到一些小的 bug,在帮客户解决这些 bug 的时候就顺手将处理的代码提交给了开源作者,惊喜的是作者竟然真的收录我提交的代码,这让我收获了满满的成就感,本来个人的技术是偏于后端 PHP 的,对前后端分离技术实践较少,但庆幸的是这套开源系统是基于前后端分离开发,在使用过程中多少是有一些障碍,正是因为这些障碍,让我不断的学习新技术,去了解前端非常优秀的 Vue.js 框架,自己在前端技术上有了质的提升,这套系统确实减少了我重复造轮子的工作量,也让我学习了很多! + +开源是一件非常有意义的事情,正因为这个开源项目给了我很大的启发,我自己也在着手开发一个开源项目,希望把自己多年来积累的经验融入到这个开源项目,帮助更多人,也满足了自己在技术世界遨游的小梦想! + diff --git "a/src/story/stories/\351\233\252\345\261\261\345\207\214\347\213\220\347\232\204\345\274\200\346\272\220\346\225\205\344\272\213.md" "b/src/story/stories/\351\233\252\345\261\261\345\207\214\347\213\220\347\232\204\345\274\200\346\272\220\346\225\205\344\272\213.md" index e7c6272479d62a5e6751ed10082927144ab19429..582aacfb59b2b8f7c2a91c9b0882949c1bf22b75 100644 --- "a/src/story/stories/\351\233\252\345\261\261\345\207\214\347\213\220\347\232\204\345\274\200\346\272\220\346\225\205\344\272\213.md" +++ "b/src/story/stories/\351\233\252\345\261\261\345\207\214\347\213\220\347\232\204\345\274\200\346\272\220\346\225\205\344\272\213.md" @@ -1,151 +1,151 @@ ---- -title: 我与开源指北的故事 -author: 雪山凌狐 -date: 2021-01-19 -permalink: /story/xueshanlinghu ---- - -## 前言 - -### 关于我 - -我是`雪山凌狐`,一位希望对这个世界做点贡献的开源爱好者。擅长 Python、易语言等的开发和教学。目前致力于帮助更多的小白开发者或业余爱好者踏入编程的大门,有自己的编程教学网站。在国外留学的时候,就有接触到开源的思想,对此很是认可,虽然目前自己的开源项目经验还不够充足,但仍在不断努力中。我希望能通过我的故事,影响到屏幕前的你,鼓起勇气加入到开源的行列中,为开源世界再抹上新的一束光。 - -### 关于开源指北项目 - -`开源指北`是由 Gitee 官方发起的电子书编写项目,因为一直有在开发者们中听到 **「我有想参与开源,但我不知道怎么做」** 这样的声音,网上搜索相关的资料也是五花八门、不成体系的,于是 Gitee 也以开源的形式,邀请众多开源爱好者一起分享经验,分享自己对开源的认识和参与开源实践的经历,为那些想参与开源的开发者们提供一个丰富详实的操作指南,让更多开发者认识开源、参与开源、爱上开源。 - -作为一份给开源新手的保姆级开源百科,`开源指北`力求严谨、详实,由爱好者拟稿编写,再由业界专家组审校完成,是业界不可多得的一份中文开源百科书,亦或许成为你未来学习开源路上不可不读的书籍之一。 - -点击学习开源指北:[开源指北](https://gitee.com/gitee-community/opensource-guide) - -## 邂逅开源指北 - -我与`开源指北`的故事,始于 2020 年的 10 月底,那时候正巧在 Gitee 弄我自己的项目,突然看到 Gitee 的一个悬浮图片广告出现在角落(还好我没开悬浮广告的屏蔽工具,不然要跟这个项目擦肩而过了哈哈),写的大概内容是:《开源指北》电子书,邀请广大开发者、开源爱好者、开源社区来共同编写。还有精美好礼哦! - -## 为什么决定参与贡献 - -期初我对于这类广告还是不怎么在意的,毕竟是官方的项目嘛,我的开源经验也不足,或许我写的东西入不了官方的法眼(官方:我有那么凶神恶煞么?)。不过当时有点时间,对于这样的项目还是有点兴趣的,想着以后别的大神写好了要不来观摩学习一下?于是戳开了悬浮广告链接。我没有想到的是,就是这么个简单的决定,改变了我未来的人生之路。 - -这也是我第一次去查看一个还没写好的开源电子书的项目,首先他们的协作形式就很值得我学习。那就是在 Issues 中写上一个个章节的内容和大纲供人认领,然后在具体协作时,通过 Gitee 独特的轻量 PR 的形式(也就是无需先 Fork 项目即可提交 PR)来进行稿件的提交。 - -我呢估计也是个 README 的颜控,接下来看到的是开源指北精美的 README 文件,当然要细细的品读一番。 - -接下来,我就看到了这么一段对参与编写者的要求: - -![参与编写者要求](./../../.vuepress/public/storyimg/1-1.png) - -我虽然认可开源理念,但确实感觉自己还没拥有太多的开源项目协作经验,所以第一点或许是不满足的。但是我发现,第二点我满足呀!找资料和编写文档的能力还是在的嘛。毕竟也是写过众多教案的人,对于要把一个复杂的事情给小白讲清楚,这一点我还是有信心的。 - -接下来我去看了一下编写奖励: - -![编写奖励](./../../.vuepress/public/storyimg/1-2.png) - -哇,还有证书,并且是官方证书,还能署名贡献者!还有周边T恤诶!(最一开始的确是冲着证书和T恤去的哈哈)虽然这个奖励成本并不算很高,但是可以帮助到开源新手这一点可跟我想要致力于帮助到更多的开发者的想法太契合了! - -于是我开始到 Issues 里面看,我能写什么章节。选择的时候也有些害怕,怕里面要写的内容都需要非常专业的经验才能编写的话,那我可真就是爱莫能助了。找着找着,发现有一个章节感觉自己能写得来:[尝试参与开源:提交第一个 Issue](https://gitee.com/gitee-community/opensource-guide/issues/I1TTV7)。我想,写好一个章节就好,在精而不贪多,于是就决定写这个了! - -在 Issues 中报名之后,很快得到了官方的回应,可以开始编写了!于是加了 `Gitee小助手` 的微信号,意外之喜是,小助手相当的热情,让我觉得这是一个充满活力的企业,我想这一定是很有发展前景的,于是更坚定了我一定要好好把认领的章节给写好,帮助到后面的朋友的心。 - -## 编写之路漫漫 - -### 编写准备 - -根据我的教学经验,我认为一个好的教程手册,应该致力于让读者看得懂,记得牢,而不是作者的自嗨。因此我在编写时也努力让自己的表述更加平实,让没有基础或者基础薄弱的朋友也不至于听不明白,从而放弃。 - -之前我说过,我对于开源的经验还不算特别的充足,因此为了避免我的内容权威性不足,我开始查阅资料,我选择写的是 `如何提交一个 Issue` 的章节,于是我把关于 Issue 对应的一些有价值的资料都看了个遍,同时,也参考了一下 Github 对于 Issue 帮助文档的英文资料。对于一些比较有价值的资料,我还反复看了两三遍。 - -由于这是一个有关操作指导的章节,跟具体的操作是脱不了关系的。于是我在 Gitee 建了一个自己的测试项目,针对找的资料在 Gitee 上一一测试比对,并将检查出的 Gitee 跟资料中的不同之处标出,避免最后编写的内容与 Gitee 上的实际使用体验不符。 - -![Gitee测试项目](./../../.vuepress/public/storyimg/1-3.png) - -### 初尝甜头 - -充分的了解让我对于这块的知识有了更多的把握,初始工作准备了 2~3 天后,我终于开始动笔了。首先需要完成的便是官方建议的大纲中建议的小节内容。 - -这里我编写的原则是在参考资料的基础上,一些概念解释或表述会基于自己对于 Issue 的理解来展开,尽可能让人快速理解这是一个什么东西,以及如何快速使用。 - -编写完成后,我开始提交我的第一稿稿件(因为担心到初稿截止日了没提交的不算数了,所以先提交第一稿再说),这时,我对于 PR 协作也是没太多经验的,不过想着总要跟仓库所有者讲明白我这次提交了什么,下次准备写啥来方便人家审核吧,于是就提了这么一个初稿 PR:[!30 【轻量级 PR】:update 第三部分——尝试参与开源/提交第一个 Issue.md.第一稿,后续还有补充,详见扩展信息](https://gitee.com/gitee-community/opensource-guide/pulls/30) - -![第一个PR](./../../.vuepress/public/storyimg/1-4.png) - -没想到,PR 说明内容竟成为之前提交过 PR 的作者里面最详实的,还触发了官方的隐藏奖励,官方直接在编写群里表扬了我: - -![触发隐藏奖励](./../../.vuepress/public/storyimg/1-5.png) - -一个开源爱好者的快乐就是这么简单,一个简单的肯定,足以让他激发更大的热情。这次,Gitee 官方的热情真的让我受宠若惊,于是我决定,后面的内容也要尽快完善完整,决不能让嗷嗷待哺的 Gitee 等久了。 - -### 完善补充 - -于是我利用工作之余的时间,继续完善补充内容,在编写的过程中,遇到的一些关于在 Gitee 中使用 Issue 的疑问(网上找不到答案,官方的文档也没写的那种),还得到了 Gitee 工作人员的耐心解答和截图支持,在此对他们表示感谢。几天后,新鲜出炉,内容详实的共 5 稿初稿,终于在第一阶段编写的截止日期前完成了。同时这份初稿也成为了后来专家组审校的过程中,一刀未剪,一稿通过的初稿,在此特别感谢专家组的肯定。 - -在编写完自己认领的章节的同时,我也在思考是否能为《开源指北》做更多的事情,比如是否可以根据编写规范,给其他已经编写好的内容改改错别字,通顺下语句或者优化排版等等。 - -说干就干!利用工作之余的时间,我将当时已经提交合并的所有章节内容都看了一遍,通读别的大神的作品学习的同时,修改了许多小细节内容。毕竟朋友们都说,我的性格适合做需要细心的活嘛。通过通力协作,我有了很大的成长和提高。 - -### 阅读我主编的章节 - -如果你看到这里对我编写的内容感兴趣,欢迎到这里阅读我主要编写的章节: - -[第 6 小节:提交第一个 Issue](https://gitee.com/gitee-community/opensource-guide/blob/master/%E7%AC%AC%E4%B8%89%E9%83%A8%E5%88%86%EF%BC%9A%E5%B0%9D%E8%AF%95%E5%8F%82%E4%B8%8E%E5%BC%80%E6%BA%90/%E7%AC%AC%206%20%E5%B0%8F%E8%8A%82%EF%BC%9A%E6%8F%90%E4%BA%A4%E7%AC%AC%E4%B8%80%E4%B8%AA%20Issue.md) - -## 参与后的收获或提升 - -### 技术精进 - -在技术方面,通过全程参与开源项目,对于整体项目流程有了很细致的了解。 - -同时为了写好自己认领的章节,我也对 Issue 相关的内容做了详细的理论调研。 - -单单是这样还不够,我还在 Gitee 建了个自己的仓库,对于学到的理论知识,都一一在仓库中实际测试之后,才会写到自己认领的章节中,对自己负责,也对未来阅读这本书籍的开源爱好者们负责。 - -即使现在在编写完成这个章节的内容几个月之后,我还是清晰的记得当初学过和记录过的那些知识要点,它就好像树根一样,深深的扎根在我的脑海里了,这对我未来持续参与开源贡献,是非常有帮助的。 - -感谢这样的经历,又让我成长了许多。 - -### 广交新友 - -**线上** - -真的非常喜欢开放包容的开源社区的氛围,至少 Gitee 的`开源指北`社区是这样的,有问题,大家摆事实讲道理,评论都是一大段一大段的,跟别人进行思想的碰撞其实是一件很爽的事情。因为发一条评论是经过深思熟虑的,需要好好组织语言来表达自己的观点,因此感觉发的每条技术评论都是文思泉涌的。这对于需要讨论的技术问题的进一步明确,甚至达成共识,非常有帮助。 - -在咱们编写小分队的微信群中,也结识了许多志同道合的小伙伴,许多开源大佬,未来我还需要多多向他们学习,向他们看齐,多为开源社区做贡献。 - -**线下** - -2020 年 12 月 27 号下午,深圳国际开源谷开源中国办公室举办了年度的 `Gitee Day` 线下活动,多次跟小助手说我要去你们办公的地方看看的我报名参与了此次活动,并有幸结实了一干开源大佬。 - -![Gitee Day 1](./../../.vuepress/public/storyimg/1-6.png) - -活动结束,还有幸参与了 Gitee 大家庭和开源分享嘉宾大佬们的晚宴,这对我来说真的是很珍贵的经历和宝贵的财富。晚宴上,我致力的教学布道的事情也得到了大佬们的认可和肯定,这对我来说是莫大的鼓励。 - -![Gitee Day 2](./../../.vuepress/public/storyimg/1-7.jpeg) - -我梦想着,未来在开源大佬的席位上,也有我的一席之地吧。 - -### 奖品满载而归 - -Gitee 真是一个不吝啬发奖品的好公司,由于我的积极贡献,前前后后获得了超多 Gitee 发的礼物,包括精致的证书、T恤、马克杯、鼠标垫、手机挂环、数据线、精美笔记本、双肩背包、实用手提包等等,搞得 `Gitee小助手` 都在说:你要凑个全套周边吗? - -![T恤、双肩背包、证书、精美笔记本](./../../.vuepress/public/storyimg/1-8.jpg) - -## 写给想参与开源的你 - -故事的最后,让我来给想参与开源的你说说心里话。 - -**“开源,用你的力量来帮助到更多的人。”** - -对于我接触到的生活工作圈子来说,参与开源贡献的人是比较少的,很多都是企业级别开发的项目,有着较高的保密需求,因此企业内的项目私有化的占比较大。但我看好开源社区,看好开源文化。如何在未来引领更多新的开发者进入开源的世界,为开源,为世界作出一点自己新的贡献,是我未来努力发展的方向。 - -这个世界未来发展的技术和力量一定是大家一点一滴筑成的。开源协作给了你一个很好的机会,跟全球开发者一道让这个世界变得更美好。当你和社区的努力给成千上万的人带来实质性的帮助的时候,那种成就感是无与伦比的。 - -而看完我的故事后,不要怕,赶紧去行动起来,参与到开源贡献当中,相信你会有不一样的技术收获。 - -![哈佛学习金字塔](./../../.vuepress/public/storyimg/1-12.png) - -不要担心自己的技术和贡献分享出去之后只是为别人做了嫁衣,`哈佛学习金字塔`告诉你,当你学到知识,最终实现`转教别人/立即应用`的程度时,你属于主动学习,知识的吸收效率是最高的。做出贡献,不仅是对项目做出了帮助,还练习了你编写代码的能力,训练了你与人协作的能力,对你的个人成长性极高。 - -因此,不要吝啬对开源社区做出的奉献,这个世界很多东西都是守恒的,你做出了贡献,开源世界终将回馈于你。 - -加油吧朋友!我在开源世界里等待你的到来! - +--- +title: 我与开源指北的故事 +author: 雪山凌狐 +date: 2021-01-19 +permalink: /story/xueshanlinghu +--- + +## 前言 + +### 关于我 + +我是雪山凌狐,一位希望对这个世界做点贡献的开源爱好者。擅长 Python、易语言等的开发和教学。目前致力于帮助更多的小白开发者或业余爱好者踏入编程的大门,有自己的编程教学网站。在国外留学的时候,就有接触到开源的思想,对此很是认可,虽然目前自己的开源项目经验还不够充足,但仍在不断努力中。我希望能通过我的故事,影响到屏幕前的你,鼓起勇气加入到开源的行列中,为开源世界再抹上新的一束光。 + +### 关于开源指北项目 + +开源指北是由 Gitee 官方发起的电子书编写项目,因为一直有在开发者们中听到 **「我有想参与开源,但我不知道怎么做」** 这样的声音,网上搜索相关的资料也是五花八门、不成体系的,于是 Gitee 也以开源的形式,邀请众多开源爱好者一起分享经验,分享自己对开源的认识和参与开源实践的经历,为那些想参与开源的开发者们提供一个丰富详实的操作指南,让更多开发者认识开源、参与开源、爱上开源。 + +作为一份给开源新手的保姆级开源百科,开源指北力求严谨、详实,由爱好者拟稿编写,再由业界专家组审校完成,是业界不可多得的一份中文开源百科书,亦或许成为你未来学习开源路上不可不读的书籍之一。 + +点击学习开源指北:[开源指北](https://gitee.com/gitee-community/opensource-guide) + +## 邂逅开源指北 + +我与开源指北的故事,始于 2020 年的 10 月底,那时候正巧在 Gitee 弄我自己的项目,突然看到 Gitee 的一个悬浮图片广告出现在角落(还好我没开悬浮广告的屏蔽工具,不然要跟这个项目擦肩而过了哈哈),写的大概内容是:《开源指北》电子书,邀请广大开发者、开源爱好者、开源社区来共同编写。还有精美好礼哦! + +## 为什么决定参与贡献 + +期初我对于这类广告还是不怎么在意的,毕竟是官方的项目嘛,我的开源经验也不足,或许我写的东西入不了官方的法眼(官方:我有那么凶神恶煞么?)。不过当时有点时间,对于这样的项目还是有点兴趣的,想着以后别的大神写好了要不来观摩学习一下?于是戳开了悬浮广告链接。我没有想到的是,就是这么个简单的决定,改变了我未来的人生之路。 + +这也是我第一次去查看一个还没写好的开源电子书的项目,首先他们的协作形式就很值得我学习。那就是在 Issues 中写上一个个章节的内容和大纲供人认领,然后在具体协作时,通过 Gitee 独特的轻量 PR 的形式(也就是无需先 Fork 项目即可提交 PR)来进行稿件的提交。 + +我呢估计也是个 README 的颜控,接下来看到的是开源指北精美的 README 文件,当然要细细的品读一番。 + +接下来,我就看到了这么一段对参与编写者的要求: + +![参与编写者要求](./../../.vuepress/public/storyimg/1-1.png) + +我虽然认可开源理念,但确实感觉自己还没拥有太多的开源项目协作经验,所以第一点或许是不满足的。但是我发现,第二点我满足呀!找资料和编写文档的能力还是在的嘛。毕竟也是写过众多教案的人,对于要把一个复杂的事情给小白讲清楚,这一点我还是有信心的。 + +接下来我去看了一下编写奖励: + +![编写奖励](./../../.vuepress/public/storyimg/1-2.png) + +哇,还有证书,并且是官方证书,还能署名贡献者!还有周边T恤诶!(最一开始的确是冲着证书和T恤去的哈哈)虽然这个奖励成本并不算很高,但是可以帮助到开源新手这一点可跟我想要致力于帮助到更多的开发者的想法太契合了! + +于是我开始到 Issues 里面看,我能写什么章节。选择的时候也有些害怕,怕里面要写的内容都需要非常专业的经验才能编写的话,那我可真就是爱莫能助了。找着找着,发现有一个章节感觉自己能写得来:[尝试参与开源:提交第一个 Issue](https://gitee.com/gitee-community/opensource-guide/issues/I1TTV7)。我想,写好一个章节就好,在精而不贪多,于是就决定写这个了! + +在 Issues 中报名之后,很快得到了官方的回应,可以开始编写了!于是加了 Gitee小助手的微信号,意外之喜是,小助手相当的热情,让我觉得这是一个充满活力的企业,我想这一定是很有发展前景的,于是更坚定了我一定要好好把认领的章节给写好,帮助到后面的朋友的心。 + +## 编写之路漫漫 + +### 编写准备 + +根据我的教学经验,我认为一个好的教程手册,应该致力于让读者看得懂,记得牢,而不是作者的自嗨。因此我在编写时也努力让自己的表述更加平实,让没有基础或者基础薄弱的朋友也不至于听不明白,从而放弃。 + +之前我说过,我对于开源的经验还不算特别的充足,因此为了避免我的内容权威性不足,我开始查阅资料,我选择写的是《如何提交一个 Issue》的章节,于是我把关于 Issue 对应的一些有价值的资料都看了个遍,同时,也参考了一下 GitHub 对于 Issue 帮助文档的英文资料。对于一些比较有价值的资料,我还反复看了两三遍。 + +由于这是一个有关操作指导的章节,跟具体的操作是脱不了关系的。于是我在 Gitee 建了一个自己的测试项目,针对找的资料在 Gitee 上一一测试比对,并将检查出的 Gitee 跟资料中的不同之处标出,避免最后编写的内容与 Gitee 上的实际使用体验不符。 + +![Gitee测试项目](./../../.vuepress/public/storyimg/1-3.png) + +### 初尝甜头 + +充分的了解让我对于这块的知识有了更多的把握,初始工作准备了 2~3 天后,我终于开始动笔了。首先需要完成的便是官方建议的大纲中建议的小节内容。 + +这里我编写的原则是在参考资料的基础上,一些概念解释或表述会基于自己对于 Issue 的理解来展开,尽可能让人快速理解这是一个什么东西,以及如何快速使用。 + +编写完成后,我开始提交我的第一稿稿件(因为担心到初稿截止日了没提交的不算数了,所以先提交第一稿再说),这时,我对于 PR 协作也是没太多经验的,不过想着总要跟仓库所有者讲明白我这次提交了什么,下次准备写啥来方便人家审核吧,于是就提了这么一个初稿 PR:[!30 【轻量级 PR】:update 第三部分——尝试参与开源/提交第一个 Issue.md.第一稿,后续还有补充,详见扩展信息](https://gitee.com/gitee-community/opensource-guide/pulls/30)。 + +![第一个PR](./../../.vuepress/public/storyimg/1-4.png) + +没想到,PR 说明内容竟成为之前提交过 PR 的作者里面最详实的,还触发了官方的隐藏奖励,官方直接在编写群里表扬了我。 + +![触发隐藏奖励](./../../.vuepress/public/storyimg/1-5.png) + +一个开源爱好者的快乐就是这么简单,一个简单的肯定,足以让他激发更大的热情。这次,Gitee 官方的热情真的让我受宠若惊,于是我决定,后面的内容也要尽快完善完整,决不能让嗷嗷待哺的 Gitee 等久了。 + +### 完善补充 + +于是我利用工作之余的时间,继续完善补充内容,在编写的过程中,遇到的一些关于在 Gitee 中使用 Issue 的疑问(网上找不到答案,官方的文档也没写的那种),还得到了 Gitee 工作人员的耐心解答和截图支持,在此对他们表示感谢。几天后,新鲜出炉,内容详实的共 5 稿初稿,终于在第一阶段编写的截止日期前完成了。同时这份初稿也成为了后来专家组审校的过程中,一刀未剪,一稿通过的初稿,在此特别感谢专家组的肯定。 + +在编写完自己认领的章节的同时,我也在思考是否能为《开源指北》做更多的事情,比如是否可以根据编写规范,给其他已经编写好的内容改改错别字,通顺下语句或者优化排版等等。 + +说干就干!利用工作之余的时间,我将当时已经提交合并的所有章节内容都看了一遍,通读别的大神的作品学习的同时,修改了许多小细节内容。毕竟朋友们都说,我的性格适合做需要细心的活嘛。通过通力协作,我有了很大的成长和提高。 + +### 阅读我主编的章节 + +如果你看到这里对我编写的内容感兴趣,欢迎到这里阅读我主要编写的章节: + +[第 6 小节:提交第一个 Issue](https://gitee.com/gitee-community/opensource-guide/blob/master/%E7%AC%AC%E4%B8%89%E9%83%A8%E5%88%86%EF%BC%9A%E5%B0%9D%E8%AF%95%E5%8F%82%E4%B8%8E%E5%BC%80%E6%BA%90/%E7%AC%AC%206%20%E5%B0%8F%E8%8A%82%EF%BC%9A%E6%8F%90%E4%BA%A4%E7%AC%AC%E4%B8%80%E4%B8%AA%20Issue.md) + +## 参与后的收获或提升 + +### 技术精进 + +在技术方面,通过全程参与开源项目,对于整体项目流程有了很细致的了解。 + +同时为了写好自己认领的章节,我也对 Issue 相关的内容做了详细的理论调研。 + +单单是这样还不够,我还在 Gitee 建了个自己的仓库,对于学到的理论知识,都一一在仓库中实际测试之后,才会写到自己认领的章节中,对自己负责,也对未来阅读这本书籍的开源爱好者们负责。 + +即使现在在编写完成这个章节的内容几个月之后,我还是清晰的记得当初学过和记录过的那些知识要点,它就好像树根一样,深深的扎根在我的脑海里了,这对我未来持续参与开源贡献,是非常有帮助的。 + +感谢这样的经历,又让我成长了许多。 + +### 广交新友 + +**线上** + +真的非常喜欢开放包容的开源社区的氛围,至少 Gitee 的开源指北社区是这样的,有问题,大家摆事实讲道理,评论都是一大段一大段的,跟别人进行思想的碰撞其实是一件很爽的事情。因为发一条评论是经过深思熟虑的,需要好好组织语言来表达自己的观点,因此感觉发的每条技术评论都是文思泉涌的。这对于需要讨论的技术问题的进一步明确,甚至达成共识,非常有帮助。 + +在咱们编写小分队的微信群中,也结识了许多志同道合的小伙伴,许多开源大佬,未来我还需要多多向他们学习,向他们看齐,多为开源社区做贡献。 + +**线下** + +2020 年 12 月 27 号下午,深圳国际开源谷开源中国办公室举办了年度的 Gitee Day 线下活动,多次跟小助手说我要去你们办公的地方看看的我报名参与了此次活动,并有幸结实了一干开源大佬。 + +![Gitee Day 1](./../../.vuepress/public/storyimg/1-6.png) + +活动结束,还有幸参与了 Gitee 大家庭和开源分享嘉宾大佬们的晚宴,这对我来说真的是很珍贵的经历和宝贵的财富。晚宴上,我致力的教学布道的事情也得到了大佬们的认可和肯定,这对我来说是莫大的鼓励。 + +![Gitee Day 2](./../../.vuepress/public/storyimg/1-7.jpeg) + +我梦想着,未来在开源大佬的席位上,也有我的一席之地吧。 + +### 奖品满载而归 + +Gitee 真是一个不吝啬发奖品的好公司,由于我的积极贡献,前前后后获得了超多 Gitee 发的礼物,包括精致的证书、T恤、马克杯、鼠标垫、手机挂环、数据线、精美笔记本、双肩背包、实用手提包等等,搞得 Gitee小助手都在说:你要凑个全套周边吗? + +![T恤、双肩背包、证书、精美笔记本](./../../.vuepress/public/storyimg/1-8.jpg) + +## 写给想参与开源的你 + +故事的最后,让我来给想参与开源的你说说心里话。 + +**“开源,用你的力量来帮助到更多的人。”** + +对于我接触到的生活工作圈子来说,参与开源贡献的人是比较少的,很多都是企业级别开发的项目,有着较高的保密需求,因此企业内的项目私有化的占比较大。但我看好开源社区,看好开源文化。如何在未来引领更多新的开发者进入开源的世界,为开源,为世界作出一点自己新的贡献,是我未来努力发展的方向。 + +这个世界未来发展的技术和力量一定是大家一点一滴筑成的。开源协作给了你一个很好的机会,跟全球开发者一道让这个世界变得更美好。当你和社区的努力给成千上万的人带来实质性的帮助的时候,那种成就感是无与伦比的。 + +而看完我的故事后,不要怕,赶紧去行动起来,参与到开源贡献当中,相信你会有不一样的技术收获。 + +![哈佛学习金字塔](./../../.vuepress/public/storyimg/1-12.png) + +不要担心自己的技术和贡献分享出去之后只是为别人做了嫁衣,哈佛学习金字塔告诉你,当你学到知识,最终实现“转教别人/立即应用”的程度时,你属于主动学习,知识的吸收效率是最高的。做出贡献,不仅是对项目做出了帮助,还练习了你编写代码的能力,训练了你与人协作的能力,对你的个人成长性极高。 + +因此,不要吝啬对开源社区做出的奉献,这个世界很多东西都是守恒的,你做出了贡献,开源世界终将回馈于你。 + +加油吧朋友!我在开源世界里等待你的到来! + diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/DolphinScheduler\345\246\202\344\275\225\345\270\246\351\242\206\346\210\221\350\265\260\350\277\233\345\274\200\346\272\220\347\232\204\344\270\226\347\225\214.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/DolphinScheduler\345\246\202\344\275\225\345\270\246\351\242\206\346\210\221\350\265\260\350\277\233\345\274\200\346\272\220\347\232\204\344\270\226\347\225\214.md" deleted file mode 100644 index 9dead1356426d7ccce55ff4e485a24c12c56521b..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/DolphinScheduler\345\246\202\344\275\225\345\270\246\351\242\206\346\210\221\350\265\260\350\277\233\345\274\200\346\272\220\347\232\204\344\270\226\347\225\214.md" +++ /dev/null @@ -1,33 +0,0 @@ -## 摘要 -> Apache DolphinScheduler 目前是 Apache 孵化项目,目前正在快速发展中。加入Apache DolphinScheduler社区已一年多,已有 400+ 公司在生产上使用,代码+文档贡献者近200位,社区用户4000 +人。本篇文章主要介绍我在Apache DolphinScheduler的经历及收获。 - -## 个人简介 -> 陈兴春,易观数科大数据平台测试工程师,Apache DolphinScheduler的一名 Commiter,拥有5年测试经验,平常主要负责千帆产品和DS的测试工作,喜欢专研新技术,对未知事物充满好奇心的一枚萌妹子 - -## Apache DolphinScheduler 简述 - -Apache DolphinScheduler 是一个开源的分布式去中心化、易扩展的可视化DAG大数据调度系统。 于2017年在易观数科立项,2019年3月开源,于2019年8月29日通过Apache基金会投票正式成为Apache孵化器项目。 - -Apache DolphinScheduler致力于解决数据处理流程中错综复杂的依赖关系,使调度系统在数据处理流程中开箱即用。可调度Shell、Python、SQL、数据存储、Spark、Flink、MR、HTTP、子流程、依赖、条件判断等任务,DAG可视化,支持自定义时间调度、历史数据补数、指定单个任务运行、任务/资源监控、重跑、停止、暂停、失败重试、恢复失败、恢复运行、告警、容错、全局参数、自定义参数、系统内置参数等功能。 - -## 结缘Apache DolphinScheduler - -2019年9月,我非常荣幸的加入易观数科,同时也加入了Apache DolphinScheduler社区,开始了与DolphinScheduler的成长之旅。DolphinScheduler是我参加的第一个开源项目,也正是Apache DolphinScheduler社区,让我知道中国开源正在崛起,中国开源的力量在壮大,越来越多的开发者及公司正在积极的拥抱开源。 - -## 入选commiter之路 - -初入DolphinScheduler社区时,@dailidong 冬哥说了一句让我至今也印象深刻的话:兴春,争取早日成为commiter。当时的我是不相信自己能成为commiter的,因为我不是开发,感觉没机会提交pr,何谈成为commiter。但是后面了解到成为commiter,不仅只有提交pr一条道路,只要为社区贡献一份力量,问题答疑、贡献文章、文档、社区运营宣传,都有机会成为commiter。 - -前期在@qiaozhanwei 占卫(DolphinScheduler PPMC)的帮助下,细心的帮我讲解DolphinScheduler业务、架构、部署以及各个服务之间的实现与联系,加上自己对linux、shell脚本、python、数据库及代码部署等有较好的基础,因此在短时间内就熟练的掌握DolphinScheduler并开始接管测试工作,把控DolphinScheduler每次发版质量的最后一道关卡。平时除了测试DolphinScheduler的业务,开始在社区进行答疑,处理GitHub上的issue,修改官网的文档。在测试V1.1.0到V1.2.0升级脚本时,发现install.sh中数据库类型为postgresql时,数据库连接却用的mysql,因此我的第一个pr产生了,哪怕只是改了一个简单的mysql,却是一个里程碑的开始,因为无数的pr及勇气都是第一个pr奠定的基石。后期经过不断的贡献与坚持,终于赶上第二批commiter的选拔,并成功入选成为DolphinScheduler的commiter。 - -当然,成为commiter不应该是加入开源项目的终极目标。成为commiter,拥有更大的操作权限,能更方便、更快捷的服务社区,同时对于项目及社区的发展与壮大,更多了一份责任,只有项目变强且被更多人及公司认可时,commiter的头衔才会变得更有意义。 - -## 社区氛围 - -社区最近多次在线上讨论master重构,经过几次会议后,加入讨论的社区人员越来越多,大家各抒己见,讨论技术实现的利与弊。作为一个测试人员,也许我不能提出专业的技术建议,也许整场会议我没有发言,但是我从不会缺席。在技术讨论过程中,我会关注开发的实现方式和逻辑,在后期测试的时候,我才能发现更多隐藏的测试点以及容易忽视的细节。 - -在DolphinScheduler社区,认识了很多大神,每天都在进行大脑风暴,讨论技术、架构及需求实现。他们利用自己休闲娱乐的时间,不断的为DolphinScheduler出谋划策,完善DolphinScheduler的功能,解决github上的issue。在他们身上,总能学到很多东西,不仅是在技术层面,更重要的是那份为了开源项目无私奉献的精神。也正是大家的贡献以及社区小伙伴的认可,社区用户群从当初的1个群增加到8个群,外加2个开发群,而且还在不断扩大,代码Contributors也从当初的1个人增长到148个,文档贡献者也有近50人了。还有一件非常值得庆贺的事情,Apache DolphinScheduler 2020年在数百个开源项目评选中脱颖而出荣获十大开源新锐项目。 - -## 未来期许 - -Apache DolphinScheduler正在拙壮成长,希望早日毕业成为顶级项目,而且我也坚信通过社区的力量与努力,DolphinScheduler一定会开辟出自己的一片天地,被越来越多的人熟知及应用。也希望广大同胞们的日子就如DolphinScheduler的slogan一样“调度选得好、下班回家早、调度选得对、回家安心睡”。同时,DolphinScheduler也欢迎更多的小伙伴加入社区,加入开源的队伍,为开源贡献一份力所能及的力量 \ No newline at end of file diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/README.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/README.md" deleted file mode 100644 index 08d8baf7b53c2de14e7211a99c7bf68a4ed992e8..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/README.md" +++ /dev/null @@ -1,22 +0,0 @@ -开源指北 1.0 即将上线,为了让更多开发者、开源小白更好的了解如何参与开源,欢迎有亲身参与过优秀开源项目的贡献者们在此分享自己的开源经验/故事 - -#### 投稿要求 -1. 你投稿的故事内需包含以下内容: -- 如何接触/了解到这个开源项目 -- 为什么决定参与贡献 -- 参与后的收获或提升(技术上或者生活上) -- 除以上内容之外,也欢迎为开源小白写上一句鼓励的话语(可选填,非必要内容) - -2. 投稿方式: -- 快捷入口>>[点我投稿故事](https://gitee.com/gitee-community/opensource-guide/new/master/%E5%BC%80%E6%BA%90%E6%95%85%E4%BA%8B) - -3. 注意 -- 标题需包含项目名,后缀为“.md ”,例如:子知鱼否与[开源/开源项目名]的故事.md -- 故事字数:不少于200 字 -- 广告、灌水文章不予收录 -- 开源指北 & Gitee 具有故事宣传、使用权 - -#### 参与奖励 -1. 故事被收录(合并PR)后,你将获得 Gitee 马克杯一份 -![输入图片说明](https://images.gitee.com/uploads/images/2021/0115/145253_2c255404_1899542.png "陶瓷杯.png") -2. 所有被收录的故事将会同步至即将上线的「开源指北」Pages 内,更有机会获得 Gitee x OSCHINA 官方微博、微信公众号等渠道推荐,让更多人可以看到你的故事。 \ No newline at end of file diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135029_c93ca9b3_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/135029_c93ca9b3_1277510.png" deleted file mode 100644 index 3e4a7bde9a5e2ae262be105c6c333901c7686439..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135029_c93ca9b3_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135109_5981e394_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/135109_5981e394_1277510.png" deleted file mode 100644 index 7a85ff9ec502c09fe30383387958e04873784542..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135109_5981e394_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135151_2f25f98a_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/135151_2f25f98a_1277510.png" deleted file mode 100644 index 8383d14d7832073b66cdf992174137b40a0dbd7b..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135151_2f25f98a_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135236_bd749e58_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/135236_bd749e58_1277510.png" deleted file mode 100644 index 20f39daaea6b52b56e4035aaf4b093aa543caea6..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135236_bd749e58_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135308_f229edb9_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/135308_f229edb9_1277510.png" deleted file mode 100644 index f3a6cb910290c3c1fc213c5223b984044278590c..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135308_f229edb9_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135639_bcc762e2_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/135639_bcc762e2_1277510.png" deleted file mode 100644 index 8d1a3fffce3f80613173c8c45638244e8e07919d..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/135639_bcc762e2_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140033_0d359644_1277510.jpeg" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/140033_0d359644_1277510.jpeg" deleted file mode 100644 index d6c4bfe718243db99894b03f4a2a4534f5e07020..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140033_0d359644_1277510.jpeg" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140112_5d07dcb4_1277510.jpeg" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/140112_5d07dcb4_1277510.jpeg" deleted file mode 100644 index 0b7bfc5dd42d9e8a95f3692742fc0dfc340384bb..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140112_5d07dcb4_1277510.jpeg" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140126_88806c64_1277510.jpeg" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/140126_88806c64_1277510.jpeg" deleted file mode 100644 index 1aa053b5a8a43be47b7dec054b74d4d61ebf5c05..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140126_88806c64_1277510.jpeg" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140141_14b080ec_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/140141_14b080ec_1277510.png" deleted file mode 100644 index 3258c1ceb4ce7e4b606f149a0955112ded329252..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140141_14b080ec_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140156_6dd035e9_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/140156_6dd035e9_1277510.png" deleted file mode 100644 index e34db36beae62d356360cc3423f56e5d9af9cdff..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140156_6dd035e9_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140229_324697ff_1277510.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/140229_324697ff_1277510.png" deleted file mode 100644 index b640cb13a0f8efe175a68cc1133ec6e926fc4a41..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/140229_324697ff_1277510.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/145253_2c255404_1899542.png" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/145253_2c255404_1899542.png" deleted file mode 100644 index 3d8d42e75ae38e3eeeae18325f296ff03006a045..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/145253_2c255404_1899542.png" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/20240507_220521.jpg" "b/\345\274\200\346\272\220\346\225\205\344\272\213/images/20240507_220521.jpg" deleted file mode 100644 index ab3fa31e41da760f52102bd123e0b012c559c86e..0000000000000000000000000000000000000000 Binary files "a/\345\274\200\346\272\220\346\225\205\344\272\213/images/20240507_220521.jpg" and /dev/null differ diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\342\200\234\346\210\221\347\232\204\344\270\200\345\211\202\350\211\257\350\215\257\342\200\235\344\271\213\345\274\200\346\272\220\346\214\207\345\214\227.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\342\200\234\346\210\221\347\232\204\344\270\200\345\211\202\350\211\257\350\215\257\342\200\235\344\271\213\345\274\200\346\272\220\346\214\207\345\214\227.md" deleted file mode 100644 index 8005e4f469b3065e8bf54da21de7aaffc7a11655..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\342\200\234\346\210\221\347\232\204\344\270\200\345\211\202\350\211\257\350\215\257\342\200\235\344\271\213\345\274\200\346\272\220\346\214\207\345\214\227.md" +++ /dev/null @@ -1,84 +0,0 @@ -# “我的一剂良药”之开源指北 - -> 文章较长,适合闲来无事时阅读。 - -## 开篇 - -开源指北是 Gitee 开源社区送给所有开源人的一份保姆级开源百科,它的出现让开源相关知识不再像“沧海遗珠”一样散落在瀚海苍茫,让初识开源者可以从容地面对开源之海的首次“起航”,让众多热衷开源的开源爱好者在这里畅谈其所想。 - -不得不说,开源指北项目的发起是一个非常有趣的想法,其秉持着“开源问题由开源来解决”的思想,吸引了众多开源爱好者参与到这项开源运动中来,我也是其中一员。这是我参与的第一个开源项目,在拟定标题时再三思忖,结合自身的亲身感受,最终定了这个标题。至于为什么说对我而言是“一剂良药”,在下文中我会作出解释。 - -相比“满满的正能量”,我更希望从平常视角坦诚相待,有喜悦,有悲伤,有勇往直前,有踟蹰迷茫。不管读到这篇文章的你正拥有着哪种情绪,都能从这些稀松平常的小事中有所得,然后继续努力前行,成为更好的自己。 - -接下来,分享一段普普通通、简简单单的故事。 - -## 源起 - -**“青山若无素,偃蹇不相亲。要识庐山面,他年是故人。”** - -我叫西狩,有些朋友也会叫我老江,从事 Java 开发相关工作。 - -2020年是动荡的一年。从我的大脑里进行热词分析,浮现出来了很多“动荡”的词汇。比如:“疫情”、“大选”、“制裁”、“猝死”、“内卷”等等。我们深知处在一个贩卖焦虑的时代,但有时还是会不自觉地被这些外界的焦虑所影响,对于处在人生各种分岔路口的人们而言,受到的影响可能会更大。随着时间越走越快,看到很多新鲜的事物如雨后春笋般破土而出,陌生而又新奇。就像是面对琳琅满目的商品一样,一不小心便挑花了眼。这时我们可能会迷茫,但我们深知,自己需要去做些什么来面对它们。 - -我不确定每个人是否都有过这种迷茫的经历,但就我个人而言,迷茫期是经常的,也是正常的。生活是一座围城,选择了漂泊但又渴望稳定,选择了努力但又渴望闲适。“有的人想得多却做得少”,我不确定这句话是否符合自己,但我深知自己做得还远远不够。大家应该都听过这样一句话:“学习最好的时间是十年前,其次是现在”。所以,**不要害怕迷茫,只要敢于面对迷茫并踏出下一步,那就是有意义的。** - -我不确定命运是否会眷顾内心和自己拧巴的人,但能够参与一项有意义的开源活动,我觉得自己是幸运的。一切的源头是从日常阅读公众号文章开始讲起,几个月前 [张乘辉](https://github.com/objcoding) 老师的一篇推文《使用 Hexo + Gitee 快速搭建属于自己的博客》,文章内容很简单易懂,而后我开始考虑搭建自己的博客。在搭建过程中,我 Gitee 平台上无意间看到了开源指北的开源活动,怀着一颗好奇心的自己就这样与开源指北相遇了。说实话,虽然平时也会在 Github、Gitee 上转一转,但顶多都是走马观花似的了解,并没有参与到什么开源项目中。起初自己也是随便了解一下。在了解项目简介、阅读其中几篇文章后,感觉自己对一些内容有一定的认知和共鸣,而且内容还有很多缺失,于是便尝试提交了一次 PR。 - -故事讲到这里,我可能还并不会深陷其中。在提交后的第二天,官方小伙伴 [tenngo](https://gitee.com/tenngoxars) 就合并了我的 PR。及时的正向反馈让我受到了很大的鼓舞,就像是可治百病的“一剂良药”,使我无处安放的心静了下来。于是便开始了我的第一次开源之旅。 - -## 指天说地 - -**“一点浩然气,千里快哉风。”** - -在开源指北之前,其实网络上有很多开源知识的相关文章,但太过零散,不成体系,对于想要参与开源的人并不友好。开源指北最大的意义就是对开源知识的整合,它涵盖了大部分常见的入门知识,可以帮助很多想要参与开源而不知如何入手的小伙伴,所以,我想有必要分享一下在开源指北参与过程中的感受与收获。 - -在《降临》中,有句台词让我记忆深刻:“If you immerse yourself into a foreign language, you can actually rewire your brain”。正如前文提到的迷茫期,最近一年的时间里发生了很多事情,思绪万千但却发现脚步却慢了下来。当我下意识提起自己的脚步时,却感觉似乎前方全是岔路,就在这时,开源指北出现了。在参与过程中,无论是查阅资料,还是编写文章,又或是提交 PR,都能感受到开源带给自己的活力。仔细想想,当自己毕业时,不愿在一眼望到头的生活里度过一生,那么自己对未来的迷茫和担忧就可以很好地接收了,因为这就是自己想要的生活。人生在世,不如意事常八九,大多数人都并非是一帆风顺的。**与其每日杞人忧天,不如沉下心来倾听内心的想法,然后坚定地踏出接下来的每一步。** - -在开始分享开源过程中的感悟前,先谈及了心态,是因为自己深知心态对我的重要性。在自己心静下来后,做事情的效率会有明显的提高,并且在交流、沟通以及决策上都可以更加清醒。接下来,便带着这份心态聊到哪算哪喽! - -开源与我的本职专业有着密切的联系,虽然是第一次参与开源,但自己对开源并不算陌生。曾经怀着激动的心情参加的每次 Pivotal 技术峰会、各种技术的 Meetup 以及各位大佬的技术分享,在这一刻似乎派上了一定的用场。这也说明了**平日积累的重要性**,碎片化学习虽然并不能建立起心中的一套完整的框架体系,但对自己的影响是潜移默化的。我会对每个章节进行阅读,文章结构不顺就梳理结构,上下文衔接问题就修改上下文,明显出现内容缺失就通过查阅资料再加上自己的理解进行补充。后面又进行了反复的阅读,以及关注小伙伴们提交的 PR。我们会为项目中提及的“半开源”的概念展开探讨,会对开源知识互相交流以至于忘记时间,诸如 arch、CLA、中国第一个被 OSI 认可的协议等等。我们也会因为项目中的不足而争辩,而且可能最终谁也说服不了谁,大家的思想是平等的,没有对错,而最终的结论也是有趣而一致的。那么这个结论是什么呢?其实很简单,各自提交 PR 就好了。**求同存异是开源社区的不二法则,我不认可你的观点,但我尊重你表达思想的权利。** - -因工作需要,我在 2017 年加入了 Kettle 技术交流群,经过学习掌握了它,但由于后续没有机会再使用,我对 Kettle 的熟练程度大幅度下降,更不要说现在最新的开源版本。同样的原因,我在 2019 年初加入了 Skywalking 交流群,基本属于一个“潜水者”,只是经常会查看技术交流的消息。其他社群我就不一一列举了,我之所以提到这两段经历,是想反思一下自己:为什么曾经有那么多优秀的开源项目摆在自己面前,到现在自己还是一个开源小白?我感觉有两个重要的事情自己没有做得很好:**坚持和思维模式**。 - -- 参与开源不是一蹴而就的事情,我们需要花费大量的时间来将其打造成为一个更好的东西。我因为不再使用而放弃对 Kettle 的关注,所以它自然而然就离我远去了。**其实大多数人都并非天才,能成为一个项目中优秀开源者的主要原因就是坚持。** -- 我学习 Kettle 只想使用它来解决问题,但从未想过自己还可以改变它。如果保持这样的思维模式继续下去,那么坚持的意义就是十分有限的了,因为我只是一个熟练工,可能永远都无法突破成为建筑师。**一个目标是否能够可达,有时候需要的只是一个思维的转变。** - -最近看了吴晟老师在开放原子基金会 2020 年技术峰会上发表的演讲——[开源运营治理分论坛 - Educate Community Over Support Community](https://www.bilibili.com/video/BV125411E7GK?p=1&share_medium=iphone&share_plat=ios&share_source=QQ&share_tag=s_i×tamp=1611211180&unique_k=ZKplUv)。演讲中很清晰地为大家讲解了我们在开源中应该关注的重点,解释了社区各种角色的职责,也谈及了对社区发展和社区生态的看法。当然,其中让人受益匪浅的内容还有很多,而且没有太多难理解的技术,更多的是对开源经验的分享,感兴趣的小伙伴可以了解一下。这也是我的一个小建议:**多去与他人交谈,倾听他人的想法,我们需要在思想碰撞的过程中不断刺激自己进行思维升级。** - -再分享一则个人觉得有趣的事情,每个开源项目都有自己的排版规则,在参与开源指北过程中,我在一个关于排版的开源项目中发现了一个有趣的协议:WTFPL。参考知乎问答“[什么是 WTFPL(Do What the Fuck You Want to Public License),为什么会有人使用这一授权许可?](https://www.zhihu.com/question/20865060/answer/51757033)”中的描述来了解一下: - -> 由于程序拥有所有权,所以每段代码允许大家在何种程度上自然使用就成为了一个严肃的法律问题,所以就诞生了licence这个概念。其中有一些代码是写出来让大家随意免费使用的,所以licence就要规定你可以干一切事情。可是在法律里,“允许你干任何事情”这句话并不严谨,所以随着不断的诉讼、打官司、法学家的诠释,诞生了诸如 [@IAMSK](http://www.zhihu.com/people/c55d6c118b9141f20776588b0308e586) 所说的一大堆授权协议。 -> 但是问题来了。 -> 这个协议是给程序员看的,却是由法学家和律师写的。 -> 于是随着时间的推移,这些协议变得unreadable,也就是程序员根本不可能看懂。 -> -> 而这些协议还会越来越长,随着欧美法律不断地被新的判例充实。。。。 -> -> 于是一些程序员为了反抗这一恶性循环,发明了WTFPL。 -> -> 简而言之,就是:**“你TM爱干啥干啥”** - -有趣的点在于,我仿佛能脑补出当时程序员看到冗长的法律条文和专业名词的时候抓狂的面部表情,是个很有意思的小故事。 - -最后要说一下,个人认为,开源指北项目参与门槛并不高,虽然在内容上会尽力做到精益求精,但它的受众是每一个开源人,大家都可以在这里各抒己见。这个项目的维护也会一直开放,也希望能够在以后听到更多开源故事和开源声音。**毕竟开源这件事儿,一起热闹起来才好玩嘛!** - -## 北窗之友 - -**“今日北窗下,自问何所为,欣然得三友,三友者为谁?琴罢辄举酒,酒罢辄吟诗。”** - -如果说有人问:“一次开源经历中,最重要的是什么事情?是最后的结果么?”我想可能不是。当我们去做任何一件事情的时候,都无法预料到下一秒会发生什么,更不会预料到最后的结果会是什么样子,所以结论并不适合放在开源经历的第一位。正所谓兴趣是最好的老师,与其猜测未知的结果,不如遵从本心去体会在开源中遇到的所有感受。因此,**一次成功的硕果固然可喜,但更重要的是享受过程。** - -我们可以对于开源项目的任何事情畅所欲言,可以发表自己对开源项目的理解,可以讨论目前存在的问题,还可以从交流中了解到更加广阔的开源世界。当然,开源社区不会是只有一种声音,我们可以有不同的观点,可以有分歧和争辩,还可以享受每一次思想的碰撞。除了必要的社区准则以外,我们的文字、代码以及思想都是无比自由的,或许这就是开源精神带给我的一种体验。 - -既然谈到了开源精神,那么一群志同道合的秉承开源精神的小伙伴自然是必不可少的。在此,要感谢在开源指北项目中帮助和鼓励过我的小伙伴们: - -- 感谢 [jack960330](https://gitee.com/jack960330) 对我编写修订过程中给予的专业指点,也感谢耐心的讲解和对我的认可,钦佩你的专业态度。 - -- 感谢 [taotieren](https://gitee.com/taotieren) 的中文排版指北项目,在了解一种排版规范的同时,还发现其使用的 WTFPL 开源协议——一个有趣的协议以及背后有趣的小故事。 - -- 感谢众多的开源小伙伴,我们一起沟通探讨了很多开源小知识,也通过他们了解到了很多开源项目,一起奋战的日子会是一段非常美好的回忆! - -- 感谢 Gitee 小助手带我加入开源小队,还给我邮递了那么多奖品,我会继续努力的。不辜负每一次参与! -- 感谢与开源指北的不期而遇,这是我这个冬季里最温暖的“小太阳”。 - -“琴罢辄举酒,酒罢辄吟诗”,这是我理想中的开源世界。所谓“琴”、“酒”、“诗”,是代指令自己感到美好的事物——是得到认可的喜悦,是有所收获的满足,是感受到如鱼得水般的自由。我觉得开源指北就是这样的,希望它在未来成长的路上,依旧如此自由!也希望参与开源的你——**Forever to be free !** \ No newline at end of file diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\344\274\227\351\207\214\345\257\273\345\245\271\345\215\203\347\231\276\345\272\246\344\271\213DolphinScheduler.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\344\274\227\351\207\214\345\257\273\345\245\271\345\215\203\347\231\276\345\272\246\344\271\213DolphinScheduler.md" deleted file mode 100644 index a36536d57aa55a91f078b08fb4c4ce0ca2a3f60d..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\344\274\227\351\207\214\345\257\273\345\245\271\345\215\203\347\231\276\345\272\246\344\271\213DolphinScheduler.md" +++ /dev/null @@ -1,51 +0,0 @@ - -### 前述 -#### 关于我 -我是CalvinKirs,目前是Apache DolphinScheduler的Commiter。擅长大数据olap、大数据调度、分布式组件开发等。目前专注于大数据领域核心技术研发。 -我也是一名开源爱好者,我要讲的是我从起始给 DolphinScheduler 做贡献到近期加入到易观数科大家庭的故事。 - -#### 关于 Apache DolphinScheduler社区 -Apache DolphinScheduler(incubator) 于17年在易观数科立项,19年3月开源, 19 年8月进入Apache 孵化器,社区发展非常迅速,目前已有 400+ 公司在生产上使用,代码+文档贡献者近200位,社区用户4000 +人。DolphinScheduler (简称DS) 致力于使大数据任务调度开箱即用,它以拖拉拽的可视化方式将各种任务间的关系组装成 DAG(有向无环图),并实时监控整个数据pipeline的运行状态,同时支持失败重试、重跑、恢复失败、补数等大数据常用操作 - -### 遇见DolphinScheduler - -我是一个有开源情节的人,开源以不同的方式陪伴了我相当长的一段时间,同样也给我带来了一些比较大的改变。 - -我个人接触的开源项目是比较多的,但是深度贡献的并不多,也是一个偶然的契机接触到DolphinScheduler,从此开始了深度贡献。 - -选择对味的社区其实很重要,如同恋爱一般,总需要几个回合摸索试探才能决定是否合适,DolphinScheduler社区给我的一个最大的感受就是足够包容,我不认同你,但是我支持你。这是[dailidong](https://github.com/dailidong)给我的一个最直观的感受,你的想法不成熟的时候,作为PPMC,他需要对社区负责,他可能不是很认同,但是他支持你去完善去佐证,这个过程中也是很感谢社区的一些其他伙伴,[qiaozhanwei](https://github.com/qiaozhanwei)、[Tboy](https://github.com/Technoboy-)、[gaojun2048](https://github.com/gaojun2048),[lgcarrer](https://github.com/lgcareer)(license的大佬)、[lenboo](https://github.com/lenboo)(核心流程找他就对了)等,一开始我总有种人微言轻的感觉,一般都处在旁听的状态,毕竟这些贡献者基本上都是各大公司的精英人物。后来发现是我多虑了,大神们其实非常平易近人。也是因为这些人,让我喜欢上DolphinScheduler社区。 - -### 社区带给我的影响 - -随着社区的发展,越来越多同学的加入,我们可能(甚至是必然)会在一些设计上存在一些不同的意见,但这其实也是开源的魅力,对于社区来讲,也是一种好事,不同思想的碰撞才会导致设计趋近于更加完善。也只有这样,DolphinScheduler才能更好走向全球。当然,对于个人来讲,也是一种提升,就我而言,我之前在社区讨论关于通讯序列化方案的想法,我们的导师,[吴晟老师](https://github.com/wu-sheng)问我,为什么不选择protobuf呢,我以前的认知,只体现在一个很片面的范围内,但是吴晟老师从更高层次回答了我所谓的protobuf鸡肋的地方,这确实打开了我的视野。感兴趣的可以去搜邮件列表,我所想要表达的是,开源是一个全球的舞台,会有各种不同的人进来参与,也正是由于这样,你的提升才会更大,因为你不再停留在原有的圈子原有的认知去思考,你会接受各种各样的人来进行review(不仅仅是code,同样包括一些设计等等),这种过程其实也是在逐渐拓宽自己的专业领域与认知。 - -### DolphinScheduler微内核插件化设计 - -项目的推进导致架构的变化,捐给Apache之后,意味着你要面向全球的用户,不同的用户对于不同场景的需求是不同的,我们更希望的是DolphinScheduler作为一个基础设施提供给用户,给用户提供强大的扩展能力,用户在DolphinScheduler这个平台上去快速扩充自己的功能。 - -在2020年(近期会发版),[高俊老师](https://github.com/gaojun2048)提出了微内核插件化的架构设计,拿alert来讲,我们alert发版后是支持五种告警方式,这能够满足绝大多数用户的一个需求,但依然有一些需求是没办法满足的,这个时候用户想要自己实现其实很简单,他不需要系统的去了解DolphinScheduler的整个架构,只需要关注alert的扩展接口,对于其他功能来讲是完全隔离的(这也意味着你降低了污染传递,当你的模块出现问题的时候,你不会过多影响其他模块,甚至你可以完全移除你自己的插件),这对于用户来讲,理解成本更低、开发成本测试成本同样更低,对于贡献者来讲亦是如此,降低贡献者门槛,才能使得一个项目走的更远,曲高和寡,对于开源项目来讲同样如此,DolphinScheduler社区目前有很多其他社区的贡献者,比如SkyWalking、ShardingSphere、Dubbo、TubeMq等,调度系统更是与其他大数据生态紧密结合,我们也是希望,通过微内核插件化的方式,使得各个领域的专家都可以以最低成本的贡献进来。 - -### 开源的乐趣 - -[姜宁老师](https://github.com/WillemJiang)讲,开源社区其实是一帮对的人才能够聚在一起,这种过程会让你很享受,我之前收到过一封邮件,是一个印度贡献者的,我merge了他参与Apache DolphinScheduler的第一个PR,他写了大概几百字的一封邮件,表达对于开源的向往以及询问我后续参与贡献的一个途径,我不太确定这是否会导致他从此踏上开源这条路,成为一个深度贡献者,但至少对于他来讲,这一刻他有了深度参与的一个想法,我当时也是因为首次贡献被merge之后于是踏上了开源这条路,我至今依然记得我对于Apache的第一个PR,虽然小,甚至从今天看来,那可能是我贡献的PR中最微不足道的一个,但对于我来讲,它为我打开了一扇门,所以其实到今天,我很乐意给那些初次贡献的贡献者提供深度的一个帮助,帮他们认识开源、走进开源。曾经有人为我打开了一扇门,那我希望我能够给更多的人提供走进这扇门的一个帮助,这可能也是一种属于开源人的传承(BTW,强烈推荐[ALC BeiJing](https://github.com/alc-beijing))。 - -马斯洛需求层次理论中讲到人的高级需求,其实对我来讲,通过DolphinScheduler,我达到了自我实现与尊重。 - -当我写的代码,会运行在数万台服务器上,影响几亿的用户,我也是第一次感觉作为个体和这个世界有了更加紧密的一个联系,这种内心的成就感是非常高的。 - -当我看到被我merge代码的同学发朋友圈或者邮件的时候,我内心其实也是非常愉快的,我老板说:优秀的人成就自己,卓越的人成就他人,我可能不是很优秀的人,但如果能够从一件小事上影响到别人,对于我来讲,我也是很愉悦的(成年人的快乐有时候就这么简单)。 - -### 尾篇 致下一个贡献者的你 - -[大侠](https://github.com/William-GuoWei)在ALC Beijing-开源到底有多难中以[开源,不是天才的甜点,而是勤奋者的盛宴](https://zhuanlan.zhihu.com/p/208577284)为题的分享有几句话是比较触动我的 -``` -“中国没有开源”这个观点我是不愿意相信的。我相信这一代年轻人,不仅仅是程序猿,而是越来越多的人,愿意参加到各行各业的非盈利团体当中去,贡献自己的想法、代码、知识,让这个世界变得更加美好。 - -我相信哪怕我们这一代人看不到开源的春天,我们的下一代人也不应该再看到开源的“雾霾天”。于是我们就积攒了更多的力量,筹备了一年,把我们自己内部使用的一个产品 — Dolphin Scheduler 进行了开源。 -``` -我身边参与开源的人其实蛮多的,但倘若放到整个公司来讲,其实也并不多,上家公司,产研三四百多人,但是是Apache commiter或者PMC的仅仅只有三人,然而我们整个基础设施一大半是在开源软件的基础上进行开发的(其中一大半是ASF的),对于所使用到的开源项目,我们基本都是内部单独维护了一个分支,这样做当然有好处,我们可以跑的很快,有什么问题可以很快修复,但是很少有人会把这些贡献给上游,最终结果导致和上游差异过大,彻底和社区脱节。大家的现状是很忙,没有时间思考,大多数人不断的掉进坑里面再爬出来,但如果每个人都做出一点点努力,那么这样其实成本是最少的。你贡献一点,他贡献一点,那么其实我们的工作量会减少很多,因为社区帮你做了。这也是开源的力量,还是回到那句话,一个人可以走的很快,但一群人可以走得很远。 - -熟悉吴晟老师的人都知道吴晟老师喜欢用『各怀鬼胎』来形容开源社区,我想说的是,无论你怀有什么样的心思(又或者仅仅是单纯的喜欢开源),透过开源确实可以帮你达到一些需求的满足,无论是一份光鲜的履历,或者一份 good job,或者隐形的人脉、技术实力的提升、多一点谈资等等。但这个前提是你去参与,去贡献。(BTW,我本人其实也是开源的受益者,因为参与开源,我有幸加入了易观,大多数企业对于开源贡献者还是比较友好的,吴晟老师的一次[分享](https://www.bilibili.com/video/BV17Q4y1N7iA),有数据显示:87%的雇主希望招聘到具备开源能力的员工,而55%的开源业内人士表示他们可以轻松地找到一份新工作。) - -中国并不缺乏优秀的工程师,缺乏的仅仅是如何正确的认识开源,参与开源。今天的中国开源其实已经非常好了,有很多前辈以及组织在开源这个领域为我们进行铺路布道,比如开源社、ALC Beijing等,我们所缺少的,仅仅是大家的参与。有一句很老套的话:如果不是现在,那是什么时候?如果不是你,那会是谁?我是[CalvinKirs](https://github.com/CalvinKirs),我在[DolphinScheduler](https://github.com/apache/incubator-dolphinscheduler)社区等你。 - diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\345\220\221\345\276\256\350\275\257\345\256\230\346\226\271\350\264\241\347\214\256 @types \345\214\205.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\345\220\221\345\276\256\350\275\257\345\256\230\346\226\271\350\264\241\347\214\256 @types \345\214\205.md" deleted file mode 100644 index 01e5182d2134f71f6582310c3516a84c67197bb6..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\345\220\221\345\276\256\350\275\257\345\256\230\346\226\271\350\264\241\347\214\256 @types \345\214\205.md" +++ /dev/null @@ -1,92 +0,0 @@ -在前端社区中,TypeScript 差不多是老生常谈的主题了。这不仅反映了 TypeScript 的流行度,也反映了它的学习上手成本。今天我们不来探讨 TypeScript 本身。而是记录一下我艰难地发布一个 [@types](https://www.npmjs.com/package/@types/tuya-panel-kit) 包的历程。 - -## a year ago - - - -上图是我在掘金的第一篇文章 [优雅地使用 TypeScript 开发 React Native 应用](https://juejin.cn/post/6844903843155689486) 中的一条素质问答。问题就是有些库不是 TS 写的,也没提供类型声明该怎么办。从图中可见我当时的解决方法都是不可复用且不利他的。但这就是我这一年来处理该问题的常规手段。 - -![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/04f411da146740aab8f620337a592850~tplv-k3u1fbpfcp-watermark.image) - -## DefinitelyTyped - -像是 Node 有 NPM,Java 有 Maven,TypeScript 也有它的另一半,那就是号称 GitHub review 数量之最的 [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) 项目。 - -![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d503ee17f0ab45068a0d50a4d6f6034a~tplv-k3u1fbpfcp-watermark.image) - -在 TypeScript 大规模应用之前,社区已经有超过 90% 的顶级 JavaScript 库,或基于 Flow 编写的库(React 系)。如果没有 DefinitelyTyped 项目,这些库想要提供类型支持,无疑只有完全重构代码。这既不现实也没必要。 - -> 鉴于 DefinitelyTyped 的作用,我们说 DefinitelyTyped 让 TypeScript 再次伟大也不为过。 - -DefinitelyTyped 目前是由微软官方维护的开源项目,参与的方式和 Homebrew 差不多,都是基于 GitHub 的工作流: - -1. fork [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) 到自己的账号下 -2. 添加自己的包并编写类型声明 -3. 提交 PR -4. 官方 review 并合并发布到 NPM - -## 艰辛的贡献历程 - -1、检查是否已存在同名的包: - -```sh -npm info @types/tuya-panel-kit -``` - -2、安装 dts-gen: - -```sh -npm install -g dts-gen -``` - -3、生成新包 - -```sh -dts-gen --dt --name tuya-panel-kit --template module -``` - -4、格式化代码 - -```sh -npm run prettier -- --write types/tuya-panel-kit/**/*.ts -``` - -这一步务必要执行,因为 DefinitelyTyped 十分严格,格式不对过不了 CI。过不了 CI,就只配合机器人对话: - -![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/140adf442a17460aa845aef8e4b8ac18~tplv-k3u1fbpfcp-watermark.image) - -5、dtslint - -```sh -yarn lint tuya-panel-kit -``` - -这一步是最让人头大的一步,Definitely 的规则可谓严苛,真就对的起它的 SLOGAN: - -> The repository for high quality TypeScript type definitions - -我梳理了一下成功路上的绊脚石: - -1、 [Cannot find module 'csstype' when npm run lint package-name](https://github.com/DefinitelyTyped/DefinitelyTyped/issues/24788) - -这是一个流程 BUG,如果你的包依赖了 react,你需要执行 `cd types/react && npm install` 和 `cd ~/.dts/typescript-installs/3.2/ && npm install` - -2、如果你的包依赖了别的外部库,需要添加到 [microsoft/DefinitelyTyped-tools](https://github.com/microsoft/DefinitelyTyped-tools/pull/165/files) 项目中,否则 CI 不给过。 - -3、你的类型声明可能有很多不符合 dtslint 的标准,我看到有的包是在 `tslint.json` 中配置禁用掉部分规则,但是我做了尝试后被人工拒绝了。 - -![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fafa598fac2e4015ab496cc15fd94496~tplv-k3u1fbpfcp-watermark.image) - -然后我尝试在顶部加入 `// tslint:disable:max-line-length` 禁用规则,在说明原因后通过了 Review。就在发稿时,最新 PR 却因为一个禁用规则,被要求修改: - -![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/21a0b43a6f464c47a1b94a5fc7ed619f~tplv-k3u1fbpfcp-watermark.image) - -## 规范的重要性 - -刚开始时,这种严苛漫长的 review 流程着实让我头大。但在提过 4 个 PR 都被合并后,我发现 review 的人关心的是你为什么要这么写,是不是有什么不得已的苦衷,是否符合高质量的要求。 - -在参与 DefinitelyTyped 的协作中,我越来越发现规范的重要。如此体量的项目,如果没有严格有效的规范约束,势必会被开发者抛弃。那我们来看看 DefinitelyTyped 中是如何约束的: - -1. [dtslint](https://github.com/microsoft/dtslint) :微软专门写的用来检验类型声明文件的工具。正是因为它,我做了大量优化工作。 -2. 机器人 🤖(dt-mergebot、dt-review-bot、typescript-bot-watchdog):在你的代码通过所有规范之前,都是这些机器人在和你交互。大家感兴趣的话,之后我会单独出一篇解析的文章 -3. 尽职尽责的维护:虽然有时 review 速度明显很慢(可能因为国外疫情)。但是这些维护者真的是尽职尽责的 review 你的代码。机器再厉害也只是一个减少工作量的工具。我们应该致敬的还是这些为社区默默奉献的人。 diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\345\274\200\346\272\220\346\234\211\351\255\224\345\212\233-DolphinScheduler\345\222\214\346\210\221\347\232\204\345\274\200\346\272\220\345\216\206\347\250\213.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\345\274\200\346\272\220\346\234\211\351\255\224\345\212\233-DolphinScheduler\345\222\214\346\210\221\347\232\204\345\274\200\346\272\220\345\216\206\347\250\213.md" deleted file mode 100644 index 67376a3e04867b6de33b3142f7815651176fa639..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\345\274\200\346\272\220\346\234\211\351\255\224\345\212\233-DolphinScheduler\345\222\214\346\210\221\347\232\204\345\274\200\346\272\220\345\216\206\347\250\213.md" +++ /dev/null @@ -1,31 +0,0 @@ -## 开源有魔力-DolphinScheduler和我的开源历程 - - 鲍亮(leonbao),目前在易观数科大数据平台,负责平台建设工作,开源爱好者,DolphinScheduler PPMC, 一个有梦想的程序员。 - -### 开源的思考 - - “What's your Legacy?” 易观的大家长Edward在一次季度总结中曾提到这样一句话,引发了我对于legacy的思考:写出一个让世界上更多人使用的软件,这也许是大多数程序员的初心和梦想,而能让这种想法实现的就是开源。站在2021年的里程碑旁回首过去,DolphinScheduler已经在这条路上奔跑了2年。就像电影里的镜头一样,阿甘坚持不懈跑步,周围聚集了越来越多的同行者,越来越多的人加入到开发者队伍中,开源的魔力正在让我们的梦想照进现实。新年伊始,我想回忆一下我们的开源之路。 - - 2017年底,易观的千帆项目每天数百亿条数据,月活6.2亿,上万个任务需要处理近7PB的数据,用的调度系统,却年久失修,遇到问题就焦头烂额,对于新的需求也是束手无策,所以更换调度系统势在必行。众所周知,互联网公司用得最多的就是开源产品,我们调研了市面上主流的开源调度,比如oozie、Azkaban、Airflow等开源调度还有几个商业调度,均不能很好满足我们好用、易用的目标,所以站在众多开源产品的肩膀上,我们确定了以无中心为设计思想的架构。践行易观”数据能力平民化”的理念,最开始的时候我们就决定将此项目开源,故而将业务系统彻底与调度解耦,这也是最初设计的一个重要思想。 - - DS每个功能、每个流程的诞生都伴随着团队内的一场场激烈的思想碰撞、一次次不分昼夜的战斗。为了更快实现整个流程和验证产品的有效性,我们使用了最简单的数据库轮询方案,这也为提升并发量和减少资源消耗带来了不小的挑战,这两点和扩展性的优化也是DS将来最主要的任务。同时,也让我们认识到开源的魔力所在,只依靠一个小圈子做软件会产生局限性,有更多的开发者和思想交汇,产品才能更好得发展。 - - 当第一个版本出来以后,产品名字确定为易调度(EasyScheduler),CTO郭大侠曾提出理念”开箱即用”,简而言之就是一个“易“字,另一方面,在易观的企业文化中,“易”也可以拆分成日月两字,象征着变化即永恒。经过一系列的测试,又历经3个月时间,终于把千帆的任务都转移到易调度里面。后面又从各大朋友圈里找了一些种子用户验证产品的功能。2019年3月,经过一系列重构,发布了第一个开源版本1.0,并在github上开放所有源代码。 - -### 开放源代码=开源? - - 开放源代码=开源?在了解ASF以前,我一直都是这么认为的。但其实,开源的目的不仅仅是能让更多人用上好的产品,更重要的是让更多的人来提高和完善这个调度系统,让它变得更易用,更好用,正所谓“独行快,众行远“。 - - 在开放源代码以后的一段时间内,我们发现一个问题:并没有多少开发者加入,也没有新的代码和新的思想出现。后来各种不放弃的执着让我们遇到了Apache Kylin现在的VP史少峰老师,史老师给我们引荐了我们现在的Mentor陈亮老师和Champion - 吴晟老师,Apache SkyWalking Founder。在一个阳光明媚的下午,吴晟老师给我们普及了apache 相关知识,为我们打开了开源世界的新大门。”Community > Code”,决策透明才能让更多人加入,进而形成一个公平、平等、精英治理的社区。我们确定了新的目标:加入apache,建立apache way的社区。 - - 加入apache当然没有那么容易,每个人对于apache way的理解也都不一样,在对项目的重构和升级过程中,大家又加入到充满激情的战斗中,纷纷在微信群里提出很多想法,这让我们认识到以前社区没有更多的开发者和思想,就是因为决策不透明。2019年8月底,经过前期准备,DS终于顺利进入孵化器,成为apache的孵化项目。 - -### 我和社区的进步 - - 在一年多的孵化期间,我们走过很多弯路,也学到了很多宝贵的经验,社区也取得了很大的进步。为了更好了解apache,我个人读了很多书,学习了其他项目的代码,了解了其他社区的构建方式,这让我受益匪浅。社区也是一样,从最开始的第一个版本需要4个月发出,到现在基本上每个月都会发一个版本;从最开始的不知道怎么使用邮件列表到现在的大事小情都想通过邮件列表来通知和讨论;从最开始的迷惑于license,到现在对各种license都略知一二。。。 - - 个人和社区都在不断发展,这一点正如ASF member姜宁老师的比喻:“在武林中立一个山头,带一群人成长“。每次通过邮件列表、issue、pull request的交流都像是在和不同的高手过招,在这个过程中,每个人都能学到新的招数,加深自己的内功。到目前为止,社区也贡献了很多有价值的功能,小到各种bug的fix、文档的注释, 大到各种重构、github action、k8s等等。 - -### 呼唤更多同行者 - - 从Dolphinscheduler诞生到现在,已经有超过150个代码贡献者和近50个文档贡献者加入我们的队伍,在“公平、开放、透明“的加持下,只要你怀有同样的初心,欢迎与我们同行,用开源的魔力把梦想变成现实! diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\345\274\200\346\272\220\347\244\276\345\214\272\345\256\236\344\271\240\350\256\260 - \346\210\221\346\212\212 openEuler \347\247\273\346\244\215\345\210\260\344\272\206 Windows WSL.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\345\274\200\346\272\220\347\244\276\345\214\272\345\256\236\344\271\240\350\256\260 - \346\210\221\346\212\212 openEuler \347\247\273\346\244\215\345\210\260\344\272\206 Windows WSL.md" deleted file mode 100644 index 5dea03eda8663a720795979d8f44e79cac059fee..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\345\274\200\346\272\220\347\244\276\345\214\272\345\256\236\344\271\240\350\256\260 - \346\210\221\346\212\212 openEuler \347\247\273\346\244\215\345\210\260\344\272\206 Windows WSL.md" +++ /dev/null @@ -1,82 +0,0 @@ -# 开源社区实习记 - 我把 openEuler 移植到了 Windows WSL - -![1](https://gitee.com/ouyanghaitao/images/raw/master/1.png) - -## 初入华为,确定目标 - -我叫王海涛,哈尔滨工业大学(深圳)校区计算机专业的大三学生。 - -为了准备第一届全国大学生操作系统比赛,我的老师建议参加一些RISC-V相关的比赛,提前熟悉RISC-V,为从零写内核做好准备。于是我在2020年寒假期间参加了“2020 openEuler 高校开发者大赛”,选择的题目是“为openEuler-RISC-V添加Grub的引导启动方式”。从安装openEuler、注册gitee账号,再到用QEMU模拟RISC-V、学习Grub,这个比赛让我学到了操作系统启动流程相关的硬核知识,也让我开始了解openEuler开源社区。 - -带着对openEuler社区的好奇以及对华为公司实习的向往,在2021年1月份,我向负责华为四大开源社区运营的华为计算开源开发与运营部投递了简历。经历了3个月的漫长等待,终于如愿以偿收到了华为实习的Offer,获得了深度参与openEuler社区开发、运营的机会。 - -在社区实习几天后,我发现在学校深受大家欢迎的WSL居然还不支持openEuler。WSL即Windows Subsystem for Linux,是 Microsoft 原生的虚拟化方案,能用更快的速度、更少的磁盘,运行各种 Linux发行版,目前主流的Linux发行版都支持: - -![2](https://gitee.com/ouyanghaitao/images/raw/master/2.png) - -于是我心想,要不我来补上这块空缺吧。和导师沟通后,导师非常支持我的想法。就这样,我的第一个实习任务就确定了—— 将openEuler发行版移植到Windows WSL。 - -## 提前完成?准备发布? - -阅读了WSL相关文档后,我确定Windows WSL可以导入任意的Linux发行版,对于openEuler 而言是没有任何限制的。 - -首先是需要一个Linux发行版的根文件系统,使用WSL命令直接将这个文件系统导入即可。为了得到 Linux 发行版的根文件系统,微软建议使用发行版的docker官方镜像,启动容器后使用命令docker export导出容器镜像的快照作为所需的根文件系统。 - -在openEuler官网下载板块,我发现每个openEuler发行版都有对应的docker镜像。我下载了[openEuler 20.03 LTS SP1](https://repo.openeuler.org/openEuler-20.03-LTS-SP1/docker_img/x86_64/) 的docker镜像,跟着文档一步一步操作,第二天就在WSL上启动了openEuler。 - -满心欢喜的我跟着微软的 WSL 发布文档继续边学习边实践,又用了两三天成功地编译好了安装包。这样在windows下,双击安装包就能安装openEuler 的 WSL 版本。 - -安装包编译完成后,我想把项目代码上传到openEuler社区做存档。这时候我遇到了一个问题:提交代码需要挂靠到某一个SIG下。 - -但是目前并没有WSL相关的SIG,于是我阅读了openEuler官网SIG申请流程,发现如果要成立新的SIG,需要通过社区TC委员会的邮件列表发起申请。于是,我写下了人生第一封开源社区的邮件,向TC委员会提问是否需要创建WSL SIG。很快便收到TC答复,明确不需要新建一个WSL SIG,加入OS-builder SIG即可。后来便参加了OS-builder SIG 双周例会,介绍了当前移植工作以及遇到的问题,并且在OS-builder SIG以及社区帮助下,成功在OS-builder下建立了WSL仓库。 - -中间还有个有趣的小插曲,在社区发邮件期间,民族棋 SIG 的 Maintainer,同时也是为中学生做树莓派科普的袁老师找到我,说看到了我热情洋溢的邮件,问能不能代表同学们采访一下 WSL 项目,说实话当时的我实在是受宠若惊但又内心狂喜。在采访中,首先介绍了openEuler移植到WSL的进展,以及一些Linux入门的知识,其次按照袁老师的建议分享了自己高考考上哈工大(深圳)的经验与心得,同时也分享了多姿多彩的大学生活([采访链接](https://gitee.com/yuandj/siger/blob/master/%E7%AC%AC10%E6%9C%9F%20%E5%8D%97%E5%BE%81%E5%8C%97%E6%88%98%EF%BC%88%E4%B8%8A12%EF%BC%89.md#%E4%B8%80%E5%B0%81%E9%9D%A2%E6%95%85%E4%BA%8B%E9%98%B3%E5%85%89%E6%B5%B7%E6%B6%9B))。 - -在和导师沟通后我了解到,代码如果要提交到openEuler社区,必须要经过测试。如何测试呢?带着问题,我参与了QA(Quality Assurance)SIG,以及release-management SIG的例会,并在两个SIG的成员建议下,使用了最新的mugen测试框架,搭配integration-test的测试脚本,对移植的系统进行测试。在测试期间,顺便发现了一个测试脚本的bug,修补后提交了PR 。这个bug很简单,就是grep命令与后面的文件名黏在一起了,加个空格隔开就行,但是蚊子腿再小也是肉,第一次找到bug内心还是小有成就滴。 - -测试结束后,基本操作系统的功能即os-basic文件夹下的测试用例都通过了,不过还有一半的测试用例都没有通过。深入分析报错的log后发现,由于WSL缺少部分原生Linux的功能,导致了很多功能无法开启,相关测试也就无法通过。比如,WSL不支持systemctl,而大部分测试脚本都需要使用systemctl来开启系统功能再进行测试,自然WSL无法通过这些测试,所以测试只好暂时告一段落。虽然这部分测试没有通过,但我使用移植后的openEuler一段时间后没有发现问题,应该不影响正常使用。 - -将测试后的代码提交到wsl仓库,等待PR合入时,我便想同步将安装包提交到Microsoft Store。 - -## 为了发布,寻求帮助 - -为了在微软商城发布openEuler的安装包,我需要解决一些技术之外的问题,社区是寻求帮助的最佳途径。 - -比如,虽然安装包的搞定了,但是安装后在开始菜单显示的logo,效果不如Ubuntu的好。因为openEuler的logo,由蓝色的字母E以及底部的黑色字体openEuler组成。这带来两个问题,一是带文字图标在微软的开始菜单会显得比较小;另一个是我开了windows深色模式,黑色字体在深色背景下根本看不清楚。 - -简单粗暴的解决办法也很好想,我找到logo的矢量图,把字删掉,然后放大就行。但是身边的同事提醒我,去掉文字的logo还有法律效力吗?我能随便去掉一个已注册商标的文字部分,然后拿去发布吗?带着问题,我询问了社区的其他成员,最后辗转找到华为法务部的一位律师姐姐,向她请教logo的法律问题后,她给我了一个商标检索报告截图,告诉我去掉文字的logo也有法律效力。每次想起这个logo,都提醒我在开源社区开发也要注意法务合规。 - -解决了Logo问题后,便可以准备提交到微软商城了。WSL文档里提到,如果要发布,需要写邮件给WSL团队,经过他们的测试后,才能发布,于是我便第一时间写了一封英文邮件给WSL团队。 - -等了两个星期,WSL团队没有回复。我只好再发一封邮件,运气不错的是,这次等了几天后,WSL团队终于回复我了,说前段时间正处于微软一年中专门开会的月份,很忙,所以没看到邮件。并且表示,WSL移植好后可以直接提交,无需测试。 - -文档里说,如果要将软件安装包发布到微软商城,需要注册一个微软合作中心账户,这个账户分公司账户和个人账户。前者需要提交创办公司的官方证明文件,微软审核通过后才能发布软件,后者则无需微软审核。在公司与个人账户的选择之间,我想先试试能不能创建公司账号。虽然openEuler不是公司,只是一个社区,但是毕竟公司账号能支持更多人登录,且能发布特定功能的APP,权限更高。于是我在社区,找到了社区基础设施SIG的Maintainer,在他的帮助下,使用了openEuler的一个公共邮箱注册微软账号。在验证完邮箱后,微软合作中心提示,employment verification失败,需要提供openeuler.io这个域名是由我们注册的证明。于是我又向社区基础设施SIG要证明材料,得到几个管理员界面的截图后,按照微软文档里面的说明提交了材料,又开始了新的漫长的等待。 - -又是两周,微软还是没有回复。在微软合作中心的论坛中,发现有几个人卡在了相同的验证阶段,他们发帖称自己按照文档提交了证明材料后,微软拖了很久都没回应,短的几个星期,慢的几个月。但在他们发帖表示微软拖延后,都有微软的管理员立即跟进,人工帮助他们解决了验证问题。学到这招后我便在讨论区提交了support,希望有客服也来帮助我通过验证。 - -几天后,果然有从美国打来的电话与我沟通。但是我们讨论了一下午,她都没有解决我的问题。后来发现,我问题分类找错了,原因是与账号相关的问题有好几个,彼此之间都很相似。 - -在漫长的发布过程中,我学到了如果合作伙伴没有第一时间答复,应该想办法去主动沟通、推进,比如去论坛上发帖,去帮助中心找人工客服,向相关团队发邮件等。 - -## 喜提发布,收获满满 - -人工客服无法解决我的问题,我只好继续等待我的证明材料能被微软工作人员处理。运气不错的是,过了一个星期左右,微软发邮件告诉我,除了截图以外,要提供创办公司的PDF官方证明,可是openEuler是一个开源社区而不是商业公司,没有官方证明。于是经过openEuler 社区的讨论,我们决定先用个人账户发布。 - -这次使用另一个openEuler的邮箱来创建了一个微软的个人账户,由于不需要繁琐的验证,我很顺利地,提交了应用上传的所需信息。但是发布时,我却怎么也无法提交安装包,一直提示错签名不对。在翻看YouTube上微软发布软件的介绍,以及在Stack Overflow上搜索相应问题时,我发现签名需要提供开发者账号的Windows publisher ID,即CN开头的一串号码。使用这个号码来作为Visual Studio签名安装包的Publisher common name,签名后的安装包能正确被微软合作中心成功识别,于是我便成功将安装包提交到了微软合作伙伴中心。而这一点,我翻遍了微软开发文档都没找到相关提醒。 - -让人意外的是,这次没有等几个星期,而是在三天后我就收到了微软的修改建议。我按照微软要求,修改privacy链接,加上openEuler不支持Windows 10 S申明后,重新提交了应用上传请求,本以为仍需要等待一段时间才能发布,没想到数日后,商城居然可以搜到openEuler !发布成功了! - -![3](https://gitee.com/ouyanghaitao/images/raw/master/3.png) - -上面是 openEuler 在 Microsoft Store 的截图,感兴趣的朋友可以通过[链接1](https://www.microsoft.com/zh-cn/p/openeuler/9ngf0q0xp03d?rtc=1&activetab=pivot:overviewtab)来安装。需要注意的是,在安装WSL 任何发行版之前,需要先启用 WSL 这个功能,具体可以参考[链接2](https://gitee.com/openeuler/wsl)。 - -三个月的工作终于是告一段落了。在这期间,我写下了人生第一封英文邮件给微软,写下了第一封给开源社区的邮件,第一次与社区成员沟通讨论openEuler,在这个过程中,我感觉自己已经融入到了openEuler这个大家庭中。 - -同时在华为实习工作中,工作氛围很好,同事之间互助友爱。于是我决定延长实习,从原计划7月结束实习,延长到9月底结束。希望在后续的三个月实习时间里,我能学到更多,也能为openEuler做更多贡献! - -最后附上我总结的关于移植openEuler到WSL的技术文档,里面介绍了如何在WSL里安装openEuler,以及移植的过程: -https://gitee.com/openeuler/wsl 。如果有任何问题,欢迎在openEuler社区wsl仓库提 Issue,https://gitee.com/openeuler/wsl/issues 。 - -如果你想参与 openEuler 开发,可以搜索微信小程序 “openEuler”,里面有 80 多个 SIG 例会时间、议题以及 openEuler 的线上和线下的 Meetup 。你可以选择你感兴趣议题参与例会,在会议中和社区成员进行详细的沟通,也可以到现场来参与 Meetup 活动。 - -欢迎为 openEuler 社区添砖加瓦! \ No newline at end of file diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\346\204\237\350\260\242Apache DolphinScheduler\357\274\214\350\256\251\346\210\221\347\232\204\351\235\222\346\230\245\346\260\270\344\270\215\350\244\252\350\211\262.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\346\204\237\350\260\242Apache DolphinScheduler\357\274\214\350\256\251\346\210\221\347\232\204\351\235\222\346\230\245\346\260\270\344\270\215\350\244\252\350\211\262.md" deleted file mode 100644 index 9903215d46c61c9883362812d4cbfdec3be9e9b3..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\346\204\237\350\260\242Apache DolphinScheduler\357\274\214\350\256\251\346\210\221\347\232\204\351\235\222\346\230\245\346\260\270\344\270\215\350\244\252\350\211\262.md" +++ /dev/null @@ -1,80 +0,0 @@ -# 感谢Apache DolphinScheduler,让我的青春永不褪色 - -## 个人介绍 -我是李岗,是一名开源的爱好者和实践者,是Apache DolphinScheduler(incubator)的初始提交者和PPMC,也是Apache Local Community Beijing(ALC-Beijing)的member。 - -很开心、很庆幸自己可以成为开源领域的一员,更希望自己在未来不断地对开源持续探索、持续实践、持续分享,最终在开源领域贡献出自己的力量。 - -## 心路历程 - -一篇暴击心灵的文章、一场震撼人心的演讲都有可能成功让我们对开源产生好奇,产生兴趣,甚至一见钟情; - -另一方面,开源软件也在不断地改变我们的生活和工作,每一次开源软件的使用都可能让我惊叹开源软件的魅力,不知不觉我们就已经种下了一颗希望的种子,希望自己有一天也可以进入到开源领域,希望自己写的代码,做出的贡献可以影响到全世界更多的人。 - -当这些充满希望、充满梦想的种子在我们心中开始发芽的时候,总有一天他会呼唤着我们行动起来,加入到开源领域。 - -与很多开源爱好者相比,我是幸运的,在2017年的时候,为了更好地支撑易观千帆产品,公司需要自研一个分布式的任务调度系统来调度自身的任务,而易观的企业文化就是独立、勇敢、乐观、开放,那我们就决定做一个开源的系统,把代码开放出去,让更多的企业去使用,自此我就开始了自己的开源之旅。 - -万丈高楼平地起,从项目启动的那一刻,我们就确定了开源的目标,也从那一刻,开源的种子也种在了每个人的心中,它是一个使命,也是所有人的共识和承诺。 - -分秒必争,使命必达,所有人都整装待发,2019年3月,我们迎来了第一批的外部种子用户,正式发布第一个开源版本1.0.0。后续又逐步推出了1.0.1,1.0.2,1.0.3版本。 - -开源的种子已经种下,只有破土而出,才能扎根于大地,我们又开始了新的征程,我们要进入到全球最大的基金会,也就是Apache基金会。 - -目标是坚定地,征程却是充满了挑战,所幸最终我们始终坚持,迎来了曙光,迎来了2019年8月29日DolphinScheduler成功过入到Apache孵化器的消息。当看到邮件里不断地出现+1,+1,+1的时候,一切的付出都变为了收获,一切的汗水都化为了成长。 - - ## 开源能力 - -如果自己进入到开源领域是幸运的,那么当我首次从吴晟老师那里听到Apache Way的理念时,我一直在为Apache之道惊叹不已,我希望自己在未来可以去探索,去实践。 - -进入到Apache孵化器后,第一个里程碑就是要发布Apache Release,我自告奋勇充当了第一次的Release Manager,对于我印象最深的就是进行license的合规检查: - -“什么是二进制依赖和源码依赖,如何根据二进制依赖和源码依赖列出license?” - -“如何添加源码依赖?哪些license可以用于源码依赖?” - -“前端字体和图标是否符合license许可?” - -.......... - -因为Apache有着完善的法律框架和社会治理框架,对于license和商标有着近乎严苛的要求,在release的时候会进行非常仔细地检查,一开始真的没有太多的概念,而这些又特别的重要,否则就无法发版出来。我们的第一次发版就用了将近4个月的时间。 - -这里可以放一个链接(https://apache.org/legal/resolved.html#highlevel),如果大家之前也没有接触过,可以看一下,我想就可以体会出我当时的心情。 - -经历过第一次Apache Release,自己也更加体会到了Apache之道的独特魅力,精英治理、社区驱动、共识决策、透明开放都深深的吸引着我,也正是这种吸引让我继续前行。 - -2020年2月,当我在apache community的dev邮件列表里看到ALC Beijing要成立的消息时, - -就开始回想自己的apache之路,有迷茫、有困惑、有挑战、有喜悦,它既是一段充满挑战的修行,也是一段浪漫的开源之旅。ALC Beijing的成立点燃了我内心的另外一盏灯,自己不仅仅是要做apache开源软件的参与者和贡献者,也希望可以成为一名Apache开源文化传播者。自己也特别有幸可以成为ALC Beijing的成员,在这里也收获了很多,因为在这里有很多的开源前辈,并且他们都非常热心,我们在2020的年终会议上也坚定了使命:帮助更多国内优秀的开源项目进入到Apache基金会,我们要让国内更多的项目走出去,走向全世界。 - -## 开源分享 - -Apache基金会是一个大家庭,非常的平等,非常的包容,我也希望可以把自己对开源的体会分享出去,传递给更多希望进入到开源的爱好者,在这里特别让我感触的是,我在南京开源供应链峰会开源-教育分论坛上进行的一次分享,我对教育有一种特别的情结,教育是伟大而神圣的事业,教育是为天地立心,为生民立命,为往圣继绝学,为万世开太平。我仿佛看到了冥冥之中的那一丝牵引,教育,开源,两个让我魂牵梦绕,荡气回肠的梦想,让我找到了一种新的责任,新的使命。 - -2020年自己也参与到了Outreachy活动,成为了一名mentor,我会与远在海外的实习生异步沟通,我们在slack交流,在邮件列表交流,我希望在这个短暂的实习旅途里他们不仅仅可以提升代码技能,也可以体会到开源异步协作,积累开源沟通技巧! - -教育,开源这两个响亮的名字再一次响彻我的心中,我推开窗户,抬头望了一下蔚蓝的天空,眼睛盯着蔚蓝天空的白云深处,我想我已经找到了让我飞翔和驰骋的地方。 - -## 开源总结 - -参与到开源项目是很好的去提升自己技术和架构能力的途径,因为Apache的开源项目都是公开透明的,在这里不仅是代码公开透明,技术方案讨论、决策也都是公开透明的,我们都可以从github的issue和邮件列表里看到。所以只要我们持续的参与开源项目,无论是从技术广度和深度都会与不错的提升。 - -除去技术,更多的是在社区里如何讨论,如何决策,因为这里遵循着共识的机制,能不投票就不要投票,所以我们会发现很多时候对于方案的推进会相对较慢,但是它的优势是方案的讨论会更加的全面,这里其实就相当于Peer Review,我们都在通过邮件去表达想法,它一定是更加的全面和优质的,那么共识其实就是在这里找到一个平衡,从而更加稳定的去推动项目健康的向前发展。 - -因为社区的本质是人,好的代码,好的架构,好的文档都是由每一位贡献者完成的,我们在通过协作的模式去改变着这个community. - -感谢易观,感谢CTO郭炜老师,让我可以幸运的成为一名全职的开源工程师。 - -感谢我们的导师吴晟老师、史少锋老师、陈亮老师、Furkan Kamaci老师和Kevin Ratnasekera老师,感谢导师们对我们的耐心指导和每一次Apache Release的细心检查。 - -感谢每一位使用过DS的用户、每一位参与过DS社区贡献的伙伴,感谢你们愿意牺牲自己宝贵的时间与我们一同前行!感谢姜宁老师、李建盛老师、孙金城老师和娟神以及所有指导和帮助过我的各位开源大咖和贡献者。 - -太多的感谢汇成一句话,感谢所有的开源爱好者组成了一个平等、开放、精英、共识的大家庭,可以让我们一起修行、一起成长、让我们在忙碌之余依然有着诗和远方。 - -## 共同期许 - -坚持自己的理想,追逐自己的梦想,并且探索自己独立的思想的时候,我们的青春就已经开始了,希望你与开源的遇见是青春的开始,或者是青春的延续! - -我特别喜欢关于教育的一句话,教育是一棵树摇动着一棵树,一个灵魂感动着一个灵魂,其实开源也是如此,当我们作为新手时,社区会给我们提供很多帮助,而当我们不断地贡献,我们会获取到社区的信任,然后自己有了影响力,我们又开始去帮助更多的新加入开源的爱好者,这其实也是在不断地传递开源精神,传播知识和技能。 - -我也真心祝愿我们所有的开源爱好者都可以通过开源创造出一个属于自己的故事,这个故事关于独立、关于开放、关于挑战,我们选择了做一名斗士,挑战全新的异步协作模式、挑战自己的英语、挑战自己的演讲、挑战自己的写作,甚至我们会把开源当作一辈子的职业,我相信再过了5年,10年,我们一定感谢那个曾经的自己,当我们慕然回首,一定会对当初的那个自己说一句:"谢谢你,我的开源,我的青春!" diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JAP\347\232\204\346\225\205\344\272\213.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JAP\347\232\204\346\225\205\344\272\213.md" deleted file mode 100644 index 39b63647853bff9f0a0cf433443d074a163fb709..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\350\246\201\346\207\202\345\276\227\350\210\215\345\276\227\347\232\204UMS\344\270\216JAP\347\232\204\346\225\205\344\272\213.md" +++ /dev/null @@ -1,25 +0,0 @@ -## 为什么决定参与贡献 -> 1. 2020 注定是不平凡的一年, 疫情让我有更多的空余时间; -> 2. 为了给自己身上增加一点光环; -> 3. 平时每次做新项目项目都需要搞一套用户管理系统, 虽然可以搬砖, 但也繁琐, 想着正好有空, 何不自己写一套用户管理脚手架, 省的以后搬砖; 就这样有了我的开源项目[UMS](https://gitee.com/pcore/UMS ). - -#### 项目1: [UMS](https://gitee.com/pcore/UMS ) 项目: https://gitee.com/pcore/UMS -> 用户管理脚手架集成:用户密码登录、手机登录、支持所有 JustAuth 支持的第三方授权登录、验证码、基于 RBAC 的访问权限控制功能, 支持多租户、JWT、SLF4J-MDC、签到等功能。 -> 你只需要实现业务端的几个接口 **用户服务, 短信发送服务, 获取角色权限服务, JWT(可以配置是否开启)服务** 几个 API 接口就可以实现上述功能. -> 可通过属性配置高度自定义, UMS 是非侵入式的, 与业务高度解耦; 只需要专注于自己的业务逻辑。 - -#### 项目2: [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 项目: https://gitee.com/pcore/just-auth-spring-security-starter -> Spring security 与 JustAuth 集成: 支持所有 justAuth 支持的第三方登录, -> [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 项目已加入 [JustAuth](https://gitee.com/justauth ) 大家庭. - -## 参与后的收获或提升 -> 参与开源后认识了很多小伙伴, 有参与 [UMS](https://gitee.com/pcore/UMS ) 和 [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 开源的, -> 有使用 [UMS](https://gitee.com/pcore/UMS ) 和 [JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 的小伙伴, -> 以及加入了 [JustAuth](https://gitee.com/justauth ) 这个大家庭. -> 开源表面上看只有付出没有回报, 其实通过开源潜移默化的会提升自己的技术与视野, 还有机会与朋友圈, 本人也因为 [UMS](https://gitee.com/pcore/UMS ) -> 项目认识了一个小伙伴, 加入了他的创业公司. 说了这么多就一句话: 我为人人, 人人为我. - -## 如何接触/了解到这个开源项目 -> 通过第二个项目[JustAuth-security](https://gitee.com/pcore/just-auth-spring-security-starter ) 认识了 **GVP** 项目 [JustAuth](https://gitee.com/justauth ) 的作者, 也加入 [JustAuth](https://gitee.com/justauth ) 大家庭, [JustAuth](https://gitee.com/justauth ) 作者今天刚推出了新的开源项目 [JAP](https://gitee.com/fujieid/jap) 我也成为其中的一员, 希望 2021 年 [JAP](https://gitee.com/fujieid/jap) 成为又一个 **GVP** 项目. - -## 2021 加油! \ No newline at end of file diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\350\275\273\347\274\226\347\250\213\344\270\216CRMEB\346\211\223\351\200\232\347\211\210\347\232\204\346\225\205\344\272\213.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\350\275\273\347\274\226\347\250\213\344\270\216CRMEB\346\211\223\351\200\232\347\211\210\347\232\204\346\225\205\344\272\213.md" deleted file mode 100644 index 686799e1a900a38e34d557739ad71d352b2c906e..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\350\275\273\347\274\226\347\250\213\344\270\216CRMEB\346\211\223\351\200\232\347\211\210\347\232\204\346\225\205\344\272\213.md" +++ /dev/null @@ -1,6 +0,0 @@ -> 第一次听CRMEB这个名字还是一个朋友说用这个开源仓库为客户定制二开了一个项目,赚了多少多少钱,这多少让我有些嫉妒。 -刚听到这个名字时十分好奇,是CRM客户关系管理系统吗?但为什么小程序商城可以用这个来定制开发?怀着这样的一个好奇心,去搜索引擎搜索,去Gitee搜索开源项目,一看Star量已达5k之高,再看代码质量以及UI设计确实做的非常棒,看官方的简介是将客户关系管理与社交电商营销系统深度集成的一款开源系统,打通了H5端和小程序端数据互通的问题,确实很有吸引力! - -基于这样的一个机遇,自己手里的一些商业项目也转型用到了这个开源仓库,在使用过程中也遇到一些小的bug,在帮客户解决这些bug的时候就顺手将处理的代码提交给了开源作者,惊喜的是作者竟然真的收录我提交的代码,这让我收获了满满的成就感,本来个人的技术是偏于后端PHP的,对前后端分离技术实践较少,但庆幸的是这套开源系统是基于前后端分离开发,在使用过程中多少是有一些障碍,正是因为这些障碍,让我不断的学习新技术,去了解前端非常优秀的vuejs框架,自己在前端技术上有了质的提升,这套系统确实减少了我重复造轮子的工作量,也让我学习了很多! - -开源是一件非常有意义的事情,正因为这个开源项目给了我很大的启发,我自己也在着手开发一个开源项目,希望把自己多年来积累的经验融入到这个开源项目,帮助更多人,也满足了自己在技术世界遨游的小梦想! \ No newline at end of file diff --git "a/\345\274\200\346\272\220\346\225\205\344\272\213/\351\233\252\345\261\261\345\207\214\347\213\220\344\270\216\345\274\200\346\272\220\346\214\207\345\214\227\347\232\204\346\225\205\344\272\213.md" "b/\345\274\200\346\272\220\346\225\205\344\272\213/\351\233\252\345\261\261\345\207\214\347\213\220\344\270\216\345\274\200\346\272\220\346\214\207\345\214\227\347\232\204\346\225\205\344\272\213.md" deleted file mode 100644 index 9b9f6a1960ed20c256de30b6c85649f509564826..0000000000000000000000000000000000000000 --- "a/\345\274\200\346\272\220\346\225\205\344\272\213/\351\233\252\345\261\261\345\207\214\347\213\220\344\270\216\345\274\200\346\272\220\346\214\207\345\214\227\347\232\204\346\225\205\344\272\213.md" +++ /dev/null @@ -1,148 +0,0 @@ -## 我与开源指北的故事 - -### 前言 - -#### 关于我 - -我是`雪山凌狐`,一位希望对这个世界做点贡献的开源爱好者。擅长 python、易语言等的开发和教学。目前致力于帮助更多的小白开发者或业余爱好者踏入编程的大门,有自己的编程教学网站。在国外留学的时候,就有接触到开源的思想,对此很是认可,虽然目前自己的开源项目经验还不够充足,但仍在不断努力中。我希望能通过我的故事,影响到屏幕前的你,鼓起勇气加入到开源的行列中,为开源世界再抹上新的一束光。 - -#### 关于开源指北项目 - -`开源指北`是由 Gitee 官方发起的电子书编写项目,因为一直有在开发者们中听到 **「我有想参与开源,但我不知道怎么做」** 这样的声音,网上搜索相关的资料也是五花八门、不成体系的,于是 Gitee 也以开源的形式,邀请众多开源爱好者一起分享经验,分享自己对开源的认识和参与开源实践的经历,为那些想参与开源的开发者们提供一个丰富详实的操作指南,让更多开发者认识开源、参与开源、爱上开源。 - -作为一份给开源新手的保姆级开源百科,`开源指北`力求严谨、详实,由爱好者拟稿编写,再由业界专家组审校完成,是业界不可多得的一份中文开源百科书,亦或许成为你未来学习开源路上不可不读的书籍之一。 - -点击学习开源指北:[开源指北](https://gitee.com/gitee-community/opensource-guide) - -### 邂逅开源指北 - -我与`开源指北`的故事,始于 2020 年的 10 月底,那时候正巧在 Gitee 弄我自己的项目,突然看到 Gitee 的一个悬浮图片广告出现在角落(还好我没开悬浮广告的屏蔽工具,不然要跟这个项目擦肩而过了哈哈),写的大概内容是:《开源指北》电子书,邀请广大开发者、开源爱好者、开源社区来共同编写。还有精美好礼哦! - -### 为什么决定参与贡献 - -期初我对于这类广告还是不怎么在意的,毕竟是官方的项目嘛,我的开源经验也不足,或许我写的东西入不了官方的法眼(官方:我有那么凶神恶煞么?)。不过当时有点时间,对于这样的项目还是有点兴趣的,想着以后别的大神写好了要不来观摩学习一下?于是戳开了悬浮广告链接。我没有想到的是,就是这么个简单的决定,改变了我未来的人生之路。 - -这也是我第一次去查看一个还没写好的开源电子书的项目,首先他们的协作形式就很值得我学习。那就是在 Issues 中写上一个个章节的内容和大纲供人认领,然后在具体协作时,通过 Gitee 独特的轻量 PR 的形式(也就是无需先 Fork 项目即可提交 PR)来进行稿件的提交。 - -我呢估计也是个 README 的颜控,接下来看到的是开源指北精美的 README 文件,当然要细细的品读一番。 - -接下来,我就看到了这么一段对参与编写者的要求: - -![参与编写者要求](./images/135029_c93ca9b3_1277510.png "image-20210117101655413.png") - -我虽然认可开源理念,但确实感觉自己还没拥有太多的开源项目协作经验,所以第一点或许是不满足的。但是我发现,第二点我满足呀!找资料和编写文档的能力还是在的嘛。毕竟也是写过众多教案的人,对于要把一个复杂的事情给小白讲清楚,这一点我还是有信心的。 - -接下来我去看了一下编写奖励: - -![编写奖励](./images/135109_5981e394_1277510.png "image-20210117102033342.png") - -哇,还有证书,并且是官方证书,还能署名贡献者!还有周边T恤诶!(最一开始的确是冲着证书和T恤去的哈哈)虽然这个奖励成本并不算很高,但是可以帮助到开源新手这一点可跟我想要致力于帮助到更多的开发者的想法太契合了! - -于是我开始到 Issues 里面看,我能写什么章节。选择的时候也有些害怕,怕里面要写的内容都需要非常专业的经验才能编写的话,那我可真就是爱莫能助了。找着找着,发现有一个章节感觉自己能写得来:[尝试参与开源:提交第一个 Issue](https://gitee.com/gitee-community/opensource-guide/issues/I1TTV7)。我想,写好一个章节就好,在精而不贪多,于是就决定写这个了! - -在 Issues 中报名之后,很快得到了官方的回应,可以开始编写了!于是加了 `Gitee小助手` 的微信号,意外之喜是,小助手相当的热情,让我觉得这是一个充满活力的企业,我想这一定是很有发展前景的,于是更坚定了我一定要好好把认领的章节给写好,帮助到后面的朋友的心。 - -### 编写之路漫漫 - -#### 编写准备 - -根据我的教学经验,我认为一个好的教程手册,应该致力于让读者看得懂,记得牢,而不是作者的自嗨。因此我在编写时也努力让自己的表述更加平实,让没有基础或者基础薄弱的朋友也不至于听不明白,从而放弃。 - -之前我说过,我对于开源的经验还不算特别的充足,因此为了避免我的内容权威性不足,我开始查阅资料,我选择写的是 `如何提交一个 Issue` 的章节,于是我把关于 Issue 对应的一些有价值的资料都看了个遍,同时,也参考了一下 Github 对于 Issue 帮助文档的英文资料。对于一些比较有价值的资料,我还反复看了两三遍。 - -由于这是一个有关操作指导的章节,跟具体的操作是脱不了关系的。于是我在 Gitee 建了一个自己的测试项目,针对找的资料在 Gitee 上一一测试比对,并将检查出的 Gitee 跟资料中的不同之处标出,避免最后编写的内容与 Gitee 上的实际使用体验不符。 - -![Gitee测试项目](./images/135151_2f25f98a_1277510.png "image-20210117133535739.png") - -#### 初尝甜头 - -充分的了解让我对于这块的知识有了更多的把握,初始工作准备了 2~3 天后,我终于开始动笔了。首先需要完成的便是官方建议的大纲中建议的小节内容。 - -这里我编写的原则是在参考资料的基础上,一些概念解释或表述会基于自己对于 Issue 的理解来展开,尽可能让人快速理解这是一个什么东西,以及如何快速使用。 - -编写完成后,我开始提交我的第一稿稿件(因为担心到初稿截止日了没提交的不算数了,所以先提交第一稿再说),这时,我对于 PR 协作也是没太多经验的,不过想着总要跟仓库所有者讲明白我这次提交了什么,下次准备写啥来方便人家审核吧,于是就提了这么一个初稿 PR:[!30 【轻量级 PR】:update 第三部分——尝试参与开源/提交第一个 Issue.md.第一稿,后续还有补充,详见扩展信息](https://gitee.com/gitee-community/opensource-guide/pulls/30) - -![第一个PR](./images/135236_bd749e58_1277510.png "image-20210117114636492.png") - -没想到,PR 说明内容竟成为之前提交过 PR 的作者里面最详实的,还触发了官方的隐藏奖励,官方直接在编写群里表扬了我: - -![触发隐藏奖励](./images/135308_f229edb9_1277510.png "image-20210117115256768.png") - -一个开源爱好者的快乐就是这么简单,一个简单的肯定,足以让他激发更大的热情。这次,Gitee 官方的热情真的让我受宠若惊,于是我决定,后面的内容也要尽快完善完整,决不能让嗷嗷待哺的 Gitee 等久了。 - -#### 完善补充 - -于是我利用工作之余的时间,继续完善补充内容,在编写的过程中,遇到的一些关于在 Gitee 中使用 Issue 的疑问(网上找不到答案,官方的文档也没写的那种),还得到了 Gitee 工作人员的耐心解答和截图支持,在此对他们表示感谢。几天后,新鲜出炉,内容详实的共 5 稿初稿,终于在第一阶段编写的截止日期前完成了。同时这份初稿也成为了后来专家组审校的过程中,一刀未剪,一稿通过的初稿,在此特别感谢专家组的肯定。 - -在编写完自己认领的章节的同时,我也在思考是否能为《开源指北》做更多的事情,比如是否可以根据编写规范,给其他已经编写好的内容改改错别字,通顺下语句或者优化排版等等。 - -说干就干!利用工作之余的时间,我将当时已经提交合并的所有章节内容都看了一遍,通读别的大神的作品学习的同时,修改了许多小细节内容。毕竟朋友们都说,我的性格适合做需要细心的活嘛。通过通力协作,我有了很大的成长和提高。 - -#### 阅读我主编的章节 - -如果你看到这里对我编写的内容感兴趣,欢迎到这里阅读我主要编写的章节: - -[第 6 小节:提交第一个 Issue](https://gitee.com/gitee-community/opensource-guide/blob/master/%E7%AC%AC%E4%B8%89%E9%83%A8%E5%88%86%EF%BC%9A%E5%B0%9D%E8%AF%95%E5%8F%82%E4%B8%8E%E5%BC%80%E6%BA%90/%E7%AC%AC%206%20%E5%B0%8F%E8%8A%82%EF%BC%9A%E6%8F%90%E4%BA%A4%E7%AC%AC%E4%B8%80%E4%B8%AA%20Issue.md) - -### 参与后的收获或提升 - -#### 技术精进 - -在技术方面,通过全程参与开源项目,对于整体项目流程有了很细致的了解。 - -同时为了写好自己认领的章节,我也对 Issue 相关的内容做了详细的理论调研。 - -单单是这样还不够,我还在 Gitee 建了个自己的仓库,对于学到的理论知识,都一一在仓库中实际测试之后,才会写到自己认领的章节中,对自己负责,也对未来阅读这本书籍的开源爱好者们负责。 - -即使现在在编写完成这个章节的内容几个月之后,我还是清晰的记得当初学过和记录过的那些知识要点,它就好像树根一样,深深的扎根在我的脑海里了,这对我未来持续参与开源贡献,是非常有帮助的。 - -感谢这样的经历,又让我成长了许多。 - -#### 广交新友 - -**线上** - -真的非常喜欢开放包容的开源社区的氛围,至少 Gitee 的`开源指北`社区是这样的,有问题,大家摆事实讲道理,评论都是一大段一大段的,跟别人进行思想的碰撞其实是一件很爽的事情。因为发一条评论是经过深思熟虑的,需要好好组织语言来表达自己的观点,因此感觉发的每条技术评论都是文思泉涌的。这对于需要讨论的技术问题的进一步明确,甚至达成共识,非常有帮助。 - -在咱们编写小分队的微信群中,也结识了许多志同道合的小伙伴,许多开源大佬,未来我还需要多多向他们学习,向他们看齐,多为开源社区做贡献。 - -**线下** - -2020 年 12 月 27 号下午,深圳国际开源谷开源中国办公室举办了年度的 `Gitee Day` 线下活动,多次跟小助手说我要去你们办公的地方看看的我报名参与了此次活动,并有幸结实了一干开源大佬。 - -![Gitee Day 1](./images/135639_bcc762e2_1277510.png "image-20210117123912367.png") - -活动结束,还有幸参与了 Gitee 大家庭和开源分享嘉宾大佬们的晚宴,这对我来说真的是很珍贵的经历和宝贵的财富。晚宴上,我致力的教学布道的事情也得到了大佬们的认可和肯定,这对我来说是莫大的鼓励。 - -![Gitee Day 2](./images/140033_0d359644_1277510.jpeg "image-20210117123930028.jpg") - -我梦想着,未来在开源大佬的席位上,也有我的一席之地吧。 - -#### 奖品满载而归 - -Gitee 真是一个不吝啬发奖品的好公司,由于我的积极贡献,前前后后获得了超多 Gitee 发的礼物,包括精致的证书、T恤、马克杯、鼠标垫、手机挂环、数据线、精美笔记本、双肩背包、实用手提包等等,搞得 `Gitee小助手` 都在说:你要凑个全套周边吗? - -![T恤、双肩背包、证书、精美笔记本](./images/20240507_220521.jpg "image-20210117124529354.jpg") - - - -### 写给想参与开源的你 - -故事的最后,让我来给想参与开源的你说说心里话。 - -**“开源,用你的力量来帮助到更多的人。”** - -对于我接触到的生活工作圈子来说,参与开源贡献的人是比较少的,很多都是企业级别开发的项目,有着较高的保密需求,因此企业内的项目私有化的占比较大。但我看好开源社区,看好开源文化。如何在未来引领更多新的开发者进入开源的世界,为开源,为世界作出一点自己新的贡献,是我未来努力发展的方向。 - -这个世界未来发展的技术和力量一定是大家一点一滴筑成的。开源协作给了你一个很好的机会,跟全球开发者一道让这个世界变得更美好。当你和社区的努力给成千上万的人带来实质性的帮助的时候,那种成就感是无与伦比的。 - -而看完我的故事后,不要怕,赶紧去行动起来,参与到开源贡献当中,相信你会有不一样的技术收获。 - -![哈佛学习金字塔](./images/140229_324697ff_1277510.png "image-20210117132020298.png") - -不要担心自己的技术和贡献分享出去之后只是为别人做了嫁衣,`哈佛学习金字塔`告诉你,当你学到知识,最终实现`转教别人/立即应用`的程度时,你属于主动学习,知识的吸收效率是最高的。做出贡献,不仅是对项目做出了帮助,还练习了你编写代码的能力,训练了你与人协作的能力,对你的个人成长性极高。 - -因此,不要吝啬对开源社区做出的奉献,这个世界很多东西都是守恒的,你做出了贡献,开源世界终将回馈于你。 - -加油吧朋友!我在开源世界里等待你的到来! -