Mosh的课程网址
Workflows 👉 Centralized: a single repository👉 Distributed:every developer has a repository √
Centralized Workflow 平时与中央服务器交互,万一中央服务器瘫痪,各repository之间可以交互。
中央服务器放在哪?
👉 private server
👉 cloud, 如 GitHub,GitLab
具体场景:
John 和 Amy 都将 repository 拷贝到本地
John commit了一些内容,想 share 给 Amy,就从本地 repository 拷贝到中央 repository
Amy 将这些 commit 从中央 repository pull 到本地
如果和 Amy 自己的 commit 有 conflict,Amy 解决之后 push 到中央 repository
Integration-Manager 多用于Open-source project。通常有 maintainer 管理 project repository,其他的 contributors 不能直接 commit 到 project repository。
Fork project repository 到自己的 repository,然后拷贝到本地
Contributor 将自己的 commit push 到 repository
Contributor 向 maintainer 发出 pull request,希望在 project repository commit 自己的贡献
Maintainer 同意的话就从 contributor 的 repository pull 到自己的本地目录
Maintainer review 过这些 commit 觉得没问题,就可以 push 到 project repository 了。
Cloning a Repository 拷贝远程仓库到本地,仓库目前只有一个commit:
1 2 3 4 5 6 7 8 9 10 11 $ git clone https://github.com/PurpleMStone/Mars.git MarsProject Cloning into 'MarsProject' ... remote: Enumerating objects: 3, done . remote: Counting objects: 100% (3/3), done . remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Receiving objects: 100% (3/3), done . $ cd MarsProject/ (master)$ git log --oneline --all --graph * 7216ded (HEAD -> master, origin/master, origin/HEAD) Initial commit
origin 指代的是远程仓库:
1 2 3 (master)$ git remote -v origin https://github.com/PurpleMStone/Mars.git (fetch) origin https://github.com/PurpleMStone/Mars.git (push)
Fetching
1 2 (master)$ git log --oneline --all --graph * 7216ded (HEAD -> master, origin/master, origin/HEAD) Initial commit
在 remote repository 进行修改(update README.md,增加了第二行):
1 2 # Mars A new line of code
用 git fetch 获取到本地,此时 origin/master 前进了,但是本地 master 还没动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 (master)$ git fetch remote: Enumerating objects: 5, done . remote: Counting objects: 100% (5/5), done . remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), 645 bytes | 1024 bytes/s, done . From https://github.com/PurpleMStone/Mars 7216ded..e27337b master -> origin/master (master)$ git log --oneline --all --graph * e27337b (origin/master, origin/HEAD) Update README.md * 7216ded (HEAD -> master) Initial commit (master)$ git branch -vv * master 7216ded [origin/master: behind 1] Initial commit
由于没有diverse branch, 直接让本地 master fast-forward merge origin/master 就行了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (master)$ git merge origin/master Updating 7216ded..e27337b Fast-forward README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (master)$ git log --oneline --all --graph * e27337b (HEAD -> master, origin/master, origin/HEAD) Update README.md * 7216ded Initial commit (master)$ git branch -vv * master e27337b [origin/master] Update README.md (master)$ cat README.md A new line of code
而如果有 diverse branch,可能 merge 的时候会有 conflict,解决了再 merge 就行了。
Pulling
比如在本地有个commit B, 在 remote repository 有个 commit C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (master)$ echo hello > file1.txt (master)$ git add . warning: LF will be replaced by CRLF in file1.txt. The file will have its original line endings in your working directory (master)$ git commit -m "Add file1.txt" [master ce83c2f] Add file1.txt 1 file changed, 1 insertion(+) create mode 100644 file1.txt (master)$ git log --oneline --all --graph * ce83c2f (HEAD -> master) Add file1.txt * e27337b (origin/master, origin/HEAD) Update README.md * 7216ded Initial commit
在 remote repository 将 README.md update 了两次(commit C )。
现在可以用 git pull 获取 commit C 并进行 3-way merge:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 (master)$ git pull remote: Enumerating objects: 8, done . remote: Counting objects: 100% (8/8), done . remote: Compressing objects: 100% (4/4), done . remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 Unpacking objects: 100% (6/6), 1.28 KiB | 1024 bytes/s, done . From https://github.com/PurpleMStone/Mars e27337b..4085604 master -> origin/master Merge made by the 'recursive' strategy. README.md | 2 ++ 1 file changed, 2 insertions(+) (master)$ git log --oneline --all --graph * b6e7d23 (HEAD -> master) Merge branch 'master' of https://github.com/PurpleMStone/Mars |\ | * 4085604 (origin/master, origin/HEAD) Update README.md | * 3e40ffc Update README.md * | ce83c2f Add file1.txt |/ * e27337b Update README.md * 7216ded Initial commit
也可以用 git pull —rebase 将 B rebase,然后就是 linear history 了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 (master)$ git log --oneline --all --graph * ce83c2f (HEAD -> master) Add file1.txt | * 4085604 (origin/master, origin/HEAD) Update README.md | * 3e40ffc Update README.md |/ * e27337b Update README.md * 7216ded Initial commit (master)$ git pull --rebase Successfully rebased and updated refs/heads/master. (master)$ git log --oneline --all --graph * ec68ae1 (HEAD -> master) Add file1.txt * 4085604 (origin/master, origin/HEAD) Update README.md * 3e40ffc Update README.md * e27337b Update README.md * 7216ded Initial commit
Pushing 将本地的 commit push 到 remote repository,然后 remote repository 的 master 会 move forward,然后 origin/master 会 move forward.
有些情况,push 会被拒绝:
如想将C push 到 remote,但是此时别人push了个D到remote,Git为了防止你overwrite别人的work,就不让push:
如果用
remote就会丢掉D,然后让C push到remote, remote 的 master 指向C。(别用,谨慎)
好的做法是:用 git pull 在本地存下 D,然后用 3-way merge 或 rebase 的方法结合 local master 和 D,有冲突就解决冲突,然后再 git push 到 remote repository。这样,local 和remote 就一致了。
Storing Credentials windows 在 https://github.com/Microsoft/Git-Credential-Manager-for-Windows 下载
不用每次 push 都登录一次。
给最近的一次 commit 加tag,并且share 到 github 上去:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 (master)$ git tag v1.0 (master)$ git log --oneline --all --graph * 125409a (HEAD -> master, tag: v1.0, origin/master, origin/HEAD) add file2.txt * ec68ae1 Add file1.txt * 4085604 Update README.md * 3e40ffc Update README.md * e27337b Update README.md * 7216ded Initial commit (master)$ git push origin v1.0 Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 To https://github.com/PurpleMStone/Mars.git * [new tag] v1.0 -> v1.0
更新 github 的页面会发现多了一个 tag。
删除tag:
1 2 3 $ git push origin --delete v1.0 To https://github.com/PurpleMStone/Mars.git - [deleted] v1.0
更新 github 的页面会发现这个 tag被删了。但是在本地目录,tag还在:
1 2 3 4 5 6 7 8 9 10 $ git log --oneline --all --graph * 125409a (HEAD -> master, tag: v1.0, origin/master, origin/HEAD) add file2.txt * ec68ae1 Add file1.txt * 4085604 Update README.md * 3e40ffc Update README.md * e27337b Update README.md * 7216ded Initial commit $ git tag -d v1.0 Deleted tag 'v1.0' (was 125409a)
Releases 在 github 上release, 会给当前 commit 版本打一个 tag。
加上Release Notes。
如果还不是stable的版本,勾上“Pre-release”。
Sharing branches 增加分支 在本地创建了一个新分支,git push 的报错信息意思是这个branch 没有 link to origin 的 branch:
1 2 3 4 5 6 7 8 (master)$ git switch -C feature/change-password Switched to a new branch 'feature/change-password' (feature/change-password)$ git push fatal: The current branch feature/change-password has no upstream branch. To push the current branch and set the remote as upstream, use git push --set -upstream origin feature/change-password
-vv 查看当前的本地分支与远程分支的关联关系
-r 查看tracked branch (远程分支):
1 2 3 4 5 6 7 (feature/change-password)$ git branch -vv * feature/change-password 125409a add file2.txt master 125409a [origin/master] add file2.txt (feature/change-password)$ git branch -r origin/HEAD -> origin/master origin/master
将新分支push上去(-u中的u是upstream的意思):
1 2 3 4 5 6 7 8 9 (feature/change-password)$ git push -u origin feature/change-password Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 remote: remote: Create a pull request for 'feature/change-password' on GitHub by visiting: remote: https://github.com/PurpleMStone/Mars/pull/new/feature/change-password remote: To https://github.com/PurpleMStone/Mars.git * [new branch] feature/change-password -> feature/change-password Branch 'feature/change-password' set up to track remote branch 'feature/change-password' from 'origin' .
再查看一下:
本地分支和远程分支关联起来了,github上也能看到新增的分支
1 2 3 4 5 6 7 8 (feature/change-password)$ git branch -vv * feature/change-password 125409a [origin/feature/change-password] add file2.txt master 125409a [origin/master] add file2.txt (feature/change-password)$ git branch -r origin/HEAD -> origin/master origin/feature/change-password origin/master
删除分支 删除远程分支:
1 2 3 4 5 6 7 (feature/change-password)$ git push -d origin feature/change-password To https://github.com/PurpleMStone/Mars.git - [deleted] feature/change-password (feature/change-password)$ git branch -r origin/HEAD -> origin/master origin/master
但是本地分支还在,要切换回master分支删掉:
1 2 3 4 5 6 7 8 9 10 11 12 13 (feature/change-password)$ git branch -vv * feature/change-password 125409a [origin/feature/change-password: gone] add file2.txt master 125409a [origin/master] add file2.txt (feature/change-password)$ git switch master Switched to branch 'master' Your branch is up to date with 'origin/master' . (master)$ git branch -d feature/change-password Deleted branch feature/change-password (was 125409a). (master)$ git branch * master
Collaboration Workflow 1 2 本Demo展示了两个contributor是如何通过GitHub来协作的 协作者:👉 我 👉 Amy
1. 我来创建新分支 在GitHub上创建一个新分支feature/change-password,然后在本地目录下:
1 2 3 4 5 6 7 8 9 10 11 12 (master)$ git fetch From https://github.com/PurpleMStone/Mars * [new branch] feature/change-passwork -> origin/feature/change-passwork * [new tag] v1.0 -> v1.0 (master)$ git branch * master (master)$ git branch -r origin/HEAD -> origin/master origin/feature/change-passwork origin/master
我们只得到一个remote tacked branch origin/feature/change-passwork,而本地没有一个branch是feature/change-passwork。
创建一个feature/change-passwork分支,相当于一个指针指向remote branch origin/feature/change-passwork:
1 2 3 (master)$ git switch -C feature/change-passwork origin/feature/change-passwork Switched to a new branch 'feature/change-passwork' Branch 'feature/change-passwork' set up to track remote branch 'feature/change-passwork' from 'origin' .
2. 另一个contributor 现在比如说有另一个协作者Amy,将这个库clone下来:
1 2 3 4 5 6 7 8 9 10 Amy$ git clone https://github.com/PurpleMStone/Mars.git Cloning into 'Mars' ... remote: Enumerating objects: 17, done . remote: Counting objects: 100% (17/17), done . remote: Compressing objects: 100% (10/10), done . remote: Total 17 (delta 1), reused 4 (delta 0), pack-reused 0 Receiving objects: 100% (17/17), done . Resolving deltas: 100% (1/1), done . Amy$ cd Mars
查看本地分支,依然只有一个master,所以也要创建一个feature/change-passwork分支,相当于一个指针指向remote branch origin/feature/change-passwork:
1 2 3 4 5 6 7 Amy/Mars (master)$ git branch * master Amy/Mars (master)$ git switch -C feature/change-passwork origin/feature/change-passwork Switched to a new branch 'feature/change-passwork' Branch 'feature/change-passwork' set up to track remote branch 'feature/change-passwork' from 'origin' .
在这个分支下进行修改并commit,然后push到github,可以在 github 的该分支下看到这个修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Amy/Mars (feature/change-passwork)$ echo password > file1.txt Amy/Mars (feature/change-passwork) $ git commit -am "Update file1" [feature/change-passwork 244f7a7] Update file1 1 file changed, 1 insertion(+), 1 deletion(-) Amy/Mars (feature/change-passwork)$ git push Enumerating objects: 5, done . Counting objects: 100% (5/5), done . Delta compression using up to 4 threads Compressing objects: 100% (2/2), done . Writing objects: 100% (3/3), 306 bytes | 306.00 KiB/s, done . Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 To https://github.com/PurpleMStone/Mars.git 125409a..244f7a7 feature/change-passwork -> feature/change-passwork
3. 我来Merge 这时本人将GitHub的变化pull到本地,并且发现HEAD指向feature/change-passwork分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 (feature/change-passwork)$ git pull remote: Enumerating objects: 5, done . remote: Counting objects: 100% (5/5), done . remote: Compressing objects: 100% (2/2), done . remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 Unpacking objects: 100% (3/3), 286 bytes | 0 bytes/s, done . From https://github.com/PurpleMStone/Mars 125409a..244f7a7 feature/change-passwork -> origin/feature/change-passwork Updating 125409a..244f7a7 Fast-forward file1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (feature/change-passwork)$ git log --oneline --all --graph * 244f7a7 (HEAD -> feature/change-passwork, origin/feature/change-passwork) Update file1 * 125409a (tag: v1.0, origin/master, origin/HEAD, master) add file2.txt * ec68ae1 Add file1.txt * 4085604 Update README.md * 3e40ffc Update README.md * e27337b Update README.md * 7216ded Initial commit
现在希望将分支merge到master,可以发现是一个Fast-forward merge,并且查看log,两个分支在本地确实是merge了,但是origin的远程master分支还是原样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 (feature/change-passwork)$ git switch master Switched to branch 'master' Your branch is up to date with 'origin/master' . (master)$ git merge feature/change-passwork Updating 125409a..244f7a7 Fast-forward file1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (master)$ git log --oneline --all --graph * 244f7a7 (HEAD -> master, origin/feature/change-passwork, feature/change-passwork) Update file1 * 125409a (tag: v1.0, origin/master, origin/HEAD) add file2.txt * ec68ae1 Add file1.txt * 4085604 Update README.md * 3e40ffc Update README.md * e27337b Update README.md * 7216ded Initial commit
这就需要用 git push 提交merge更改。再次查看log,远程分支也merge了。并且github上也可看到merge结果(feature/change-passwork的commit merge到master上了)。
1 2 3 4 5 6 7 8 9 10 11 12 13 (master)$ git push Total 0 (delta 0), reused 0 (delta 0), pack-reused 0 To https://github.com/PurpleMStone/Mars.git 125409a..244f7a7 master -> master (master)$ git log --oneline --all --graph * 244f7a7 (HEAD -> master, origin/master, origin/feature/change-passwork, origin/HEAD, feature/change-passwork) Update file1 * 125409a (tag: v1.0) add file2.txt * ec68ae1 Add file1.txt * 4085604 Update README.md * 3e40ffc Update README.md * e27337b Update README.md * 7216ded Initial commit
4. 我来删除分支 既然 merge 了,分支留着也没用了,咱就把这分支删了吧,先删 remote branch,再删 local branch:
1 2 3 4 5 6 7 8 9 10 (master)$ git push -d origin feature/change-passwork To https://github.com/PurpleMStone/Mars.git - [deleted] feature/change-passwork (master)$ git branch feature/change-passwork * master (master)$ git branch -d feature/change-passwork Deleted branch feature/change-passwork (was 244f7a7).
看看是不是真的删了:
1 2 3 4 5 6 (master)$ git branch * master (master)$ git branch -r origin/HEAD -> origin/master origin/master
NICE.
5. 另一个contributor的同步 git pull 获取GitHub变化:
1 2 3 4 5 6 7 Amy/Mars (master)$ git pull From https://github.com/PurpleMStone/Mars 125409a..244f7a7 master -> origin/master Updating 125409a..244f7a7 Fast-forward file1.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
本地还有这个branch,删掉:
1 2 3 4 5 6 Amy/Mars (master)$ git branch feature/change-passwork * master Amy/Mars (master)$ git branch -d feature/change-passwork Deleted branch feature/change-passwork (was 244f7a7).
会发现origin还有这个branch:
1 2 3 4 Amy/Mars (master)$ git branch -r origin/HEAD -> origin/master origin/feature/change-passwork origin/master
可以这样移除(可以刷新本地仓库与远程仓库,保持这些改动的同步):
1 2 3 4 5 6 7 8 Amy/Mars (master)$ git remote prune origin Pruning origin URL: https://github.com/PurpleMStone/Mars.git * [pruned] origin/feature/change-passwork Amy/Mars (master)$ git branch -r origin/HEAD -> origin/master origin/master