{"id":17790701,"url":"https://github.com/palmerye/git-workflow-story","last_synced_at":"2025-10-19T12:44:48.548Z","repository":{"id":135932598,"uuid":"82932288","full_name":"palmerye/git-workflow-story","owner":"palmerye","description":"四种git工作流","archived":false,"fork":false,"pushed_at":"2017-02-23T16:16:27.000Z","size":2,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-07T16:36:34.022Z","etag":null,"topics":["git","gitflow","workflow"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/palmerye.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-02-23T13:57:22.000Z","updated_at":"2017-02-24T08:19:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"1cc8e650-b339-4863-807d-20cc166fb448","html_url":"https://github.com/palmerye/git-workflow-story","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palmerye%2Fgit-workflow-story","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palmerye%2Fgit-workflow-story/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palmerye%2Fgit-workflow-story/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/palmerye%2Fgit-workflow-story/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/palmerye","download_url":"https://codeload.github.com/palmerye/git-workflow-story/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246735927,"owners_count":20825335,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["git","gitflow","workflow"],"created_at":"2024-10-27T10:47:29.058Z","updated_at":"2025-10-19T12:44:48.471Z","avatar_url":"https://github.com/palmerye.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# 引言\n\n## 一言不合讲个小故事\n\n\u003e 一个和尚有水喝，两个和尚挑水喝，三个和尚没水喝。\n\n故事暴露了团队协作的问题，但接下来的故事与和尚无关，只是讲讲团队协作的事儿。\n\n## 贯穿全文的角色\n\n- 老A：技术Leader\n- 阿B：工程师\n- 小C：实习生\n\n![image](http://ohce3yxd6.bkt.clouddn.com/git/men.png)\n\n## Git工作流\n\n\u003e Git是Linux老爹的强大发明之一，用C语言编写。强大的工具也因使用情景、使用对象的不同，衍生出不同的Git工作流。\n\n- 情景一：集中式工作流\n- 情景二：功能分支工作流\n- 情景三：Gitflow工作流\n- 情景四：Forking工作流\n\n# 情景一：集中式工作流\n\n## 1. 老A初始化工程\n\n\u003e 老A在服务器上新建了一个repository（下文均以本人的[github/git-workflow-story](https://github.com/palmerye/git-workflow-story)为例子）\n\n```\nmkdir git-workflow-story \u0026\u0026 cd \"$_\"\n// 当然你也可以在bash里自定义 mkdir\u0026cd 等快捷命令\ngit init\n\ngit remote add origin https://github.com/palmerye/git-workflow-story.git\n```\n\n## 2. 阿B开始写故事\n\n\u003e 阿B的任务是在repo里写Readme(Markdown)\n\n```\nmkdir story-B \u0026\u0026 cd \"$_\"\n\ngit clone https://github.com/palmerye/git-workflow-story.git\n\nvi readme.md\n```\n于是阿B在readme里面写了一点东西，打算push到老A建的repo里。\n```\ngit add readme.md\n\ngit commit -m \"这是阿B的第一次提交\"\n\ngit push -u origin master\n// -u 参数用来初次push的时候指定默认upstream上游分支\n```\n\n## 3. 小C来啦\n\n\u003e 有一天，老A觉得阿B一个人忙不过来，找来小C来帮忙\n\n上班第一天，小C就开始忙活，也打算在老A的repo里写点东西。\n\n\n```\nmkdir story-C \u0026\u0026 cd \"$_\"\n\ngit clone https://github.com/palmerye/git-workflow-story.git\n\n```\n这个时候repo里已经有了阿B的第一次push的文件，小C突然发现有个错别字，就顺便改了。\n\n```\ngit add readme.md\n\ngit commit -m \"修改了一个错别字\"\n\ngit push -u origin master\n```\n\n## 4. 冲突\n\n阿B下午又写了点东西，和之前一样，暂存/提交/推送，突然git push失败了（错误提示本地仓库落后于远端）。于是机智的阿B有了如下操作：\n\n```\ngit pull --rebase origin master\n```\n再次push的时候发现有冲突，于是去解决冲突。发现和小C改了同一个地方，于是自己修改完继续push。\n\n\u003e git merge的冲突判定机制如下：先寻找两个commit的公共祖先，比较同一个文件分别在ours和theirs下对于公共祖先的差异，然后合并这两组差异。如果双方同时修改了一处地方且修改内容不同，就判定为合并冲突，依次输出双方修改的内容。\n\n```\ngit add . \n\ngit rebase --continue\n\ngit push origin master\n```\n## 故事完结\n\n由上面的故事我们可以看到，集中式工作流只有一条master分支，而且维护得干净一点，永远只有一条分支。多人协作的时候，推送前要确保自己本地状态和远端保持同步，因此要记得rebase。但局限就是，一条分支很难去管理多个开发状态，因此在集中式工作流的基础上，有了后文的功能分支工作流。 \n\n## 补充点东西\n\n\u003e git pull 时，--rebase参数可以让分支更整洁\n\ngit pull前\n```\n      B1---B2 master\n     /\nA---B---C origin/master\n```\n不加--rebase/相当于merge\n```\n      B1---B2 master\n     /      \\\nA---B--------C origin/master\n```\n加上--rebase，告别合并点，让分支更整洁\n```\nA---B---C---B1---B2 master, origin/master\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpalmerye%2Fgit-workflow-story","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpalmerye%2Fgit-workflow-story","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpalmerye%2Fgit-workflow-story/lists"}