fork, clone, add, commit, fetch, rebase, push流程测试


1. 假定原做者的名称叫gittest, 我叫uniquejava. java

原做者新建了一个项目叫nocrazy。 因而路径为gittest/nocrazy
作了两次提交
提交一:
a.txt
this is a

提交二:b.txt
this is b. git


2. 我cyper某天fork了这个项目,因而有origin指向uniquejava/nocrazy, 而且新增一个upstream指向原做者gittest/nocrazy

$ git clone https://git.oschina.net/uniquejava/nocrazy.git
$ cd nocrazy
➜  nocrazy git:(master) $ git remote add upstream https://git.oschina.net/gittest/nocrazy.git
➜  nocrazy git:(master) $ git remote -v
origin https://git.oschina.net/uniquejava/nocrazy.git (fetch)
origin https://git.oschina.net/uniquejava/nocrazy.git (push)
upstream https://git.oschina.net/gittest/nocrazy.git (fetch)
upstream https://git.oschina.net/gittest/nocrazy.git (push)
➜  nocrazy git:(master) $


3. gittest正常提交了一个新版本 
c.txt
this is c

git log --oneline
e63667b this is c
11f5850 this is b
1cbdb56 this is a fetch

4. Cyper想把fork同步到和gittest如出一辙,怎么办?
办法一(思考未试验):把本身的fork删除从新fork? 而后呢在本地git pull origin master

办法二:
git fetch upstream
git checkout master
git merge upstream/master

方法二须要push才能到origin么。(yes)


➜  nocrazy git:(master) $ ll
total 16
drwxr-xr-x  13 cyper  staff   442B Aug 26 05:11 .git/
-rw-r--r--   1 cyper  staff    10B Aug 26 05:07 a.txt
-rw-r--r--   1 cyper  staff    10B Aug 26 05:07 b.txt
➜  nocrazy git:(master) $ git fetch upstream
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://git.oschina.net/gittest/nocrazy
 * [new branch]      master     -> upstream/master
➜  nocrazy git:(master) $ git diff ..upstream/master
diff --git a/c.txt b/c.txt
new file mode 100644
index 0000000..5da75cf
--- /dev/null
+++ b/c.txt
@@ -0,0 +1 @@
+this is c

使用以上git diff命令能够看到author新增了一个c.txt文件。
➜  nocrazy git:(master) $ git merge upstream/master
Updating 11f5850..e63667b
Fast-forward
 c.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 c.txt
➜  nocrazy git:(master) $ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean
➜  nocrazy git:(master) $ git fetch upstream
➜  nocrazy git:(master) $ git merge upstream/master
Already up-to-date.
➜  nocrazy git:(master) $ git diff ..origin/master
diff --git a/c.txt b/c.txt
deleted file mode 100644
index 5da75cf..0000000
--- a/c.txt
+++ /dev/null
@@ -1 +0,0 @@
-this is c

经过以上能够看到git merge只是把upstream上的代码拉到(本地工做目录+本地仓库),须要咱们push origin
➜  nocrazy git:(master) $ git push origin master
Username for 'https://git.oschina.net': uniquejava
Password for 'https://uniquejava@git.oschina.net':
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 292 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://git.oschina.net/uniquejava/nocrazy.git
   11f5850..e63667b  master -> master
➜  nocrazy git:(master) $ ll
total 24
drwxr-xr-x  14 cyper  staff   476B Aug 26 05:21 .git/
-rw-r--r--   1 cyper  staff    10B Aug 26 05:07 a.txt
-rw-r--r--   1 cyper  staff    10B Aug 26 05:07 b.txt
-rw-r--r--   1 cyper  staff    10B Aug 26 05:14 c.txt

到这里, 步骤4验证结束。。。成功的将fork上的代码更新到最新版。



5. 假设上一步成功执行, 效果应该和我从新fork一遍最新的项目是同样的。 this


6. 重复3:即gitetst提交了一个新版本
d.txt
this is d. spa

7. 在6以前,Cyper由于要修复defect #1, 已经开始基于c.txt作修改。就没有来得及及时同步
cyper修改this is c变成this is c_cyper
而后正常的add, commit , (Cyper此时是否能够push?)

➜  nocrazy git:(master) ✗ $ git commit -m "[nocrazy-1] fix c."
[master 77fd57f] [nocrazy-1] fix c.
 1 file changed, 1 insertion(+), 1 deletion(-)
此时已经有了分歧。gittest上有新的提交, cyper也有新的提交。

cyper想基于最新的代码从新提交。
7-1 假定cyper没有push
他想先更新fork,而后基于 author最新的代码去作提交
git fetch upstream
git checkout master
git merge upstream/master 这一步是用git rebase upstream/master仍是用git merge upstream/master

=====

➜  nocrazy git:(master) $ git rebase origin/master(这步只是想验证base到当前base的状况,无效果)
Current branch master is up to date.
➜  nocrazy git:(master) $ git fetch upstream
remote: Counting objects: 4, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://git.oschina.net/gittest/nocrazy
   e63667b..380a8dd  master     -> upstream/master
➜  nocrazy git:(master) $ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Applying: [nocrazy-1] fix c.
➜  nocrazy git:(master) $ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean
➜  nocrazy git:(master) $

以上这步作了什么???原来git rebase upstream/master把upstream上的代码拉到(本地工做目录+本地仓库),而且自动作了合并, 因此你的本了一会儿多出来两个commit须要push, 所以有Your branch is ahead of 'origin/master' by 2 commits.
➜  nocrazy git:(master) $ git log --oneline
8530647 [nocrazy-1] fix c.
380a8dd this is d
e63667b this is c
11f5850 this is b
1cbdb56 this is a

如今只需作push origin。。。就好了!
➜  nocrazy git:(master) $ git push origin master
Username for 'https://git.oschina.net': uniquejava
Password for 'https://uniquejava@git.oschina.net':
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 566 bytes | 0 bytes/s, done.
Total 6 (delta 1), reused 0 (delta 0)
To https://git.oschina.net/uniquejava/nocrazy.git
   e63667b..8530647  master -> master

因此在发pull request 以前不要去作push . (若是在rebase以前就作了push,须要怎么补救???)


到目前为止,cyper的远程仓库中是最新的代码,而原做者的代码不新,由于他的代码没有包含你的修改

8. 发pull request
8-1, 假设gittest在你发pull request前,没有提交任何代码。。

过程很简单。
接下来gittest review,他点击某个代码变更行的前面加了一个comment: 少了一个标点符号 。。

若是你此时使用git fetch upstream会没有任何输出
而后你
➜  nocrazy git:(master) $ git rebase upstream/master
Current branch master is up to date.

这是由于你当前没有任何commit是须要rebase的, 由于全部commit都已经push到了origin. 除非。。


与时同时, gittest正常添加了一个新文件
e.txt
this is e.

你从新fetch, 
➜  nocrazy git:(master) $ git fetch upstream
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://git.oschina.net/gittest/nocrazy
   380a8dd..fd2e641  master     -> upstream/master
➜  nocrazy git:(master) $ git diff ..upstream/master
diff --git a/c.txt b/c.txt
index 3af12b3..5da75cf 100644
--- a/c.txt
+++ b/c.txt
@@ -1 +1 @@
-this is c_cyper
+this is c
diff --git a/e.txt b/e.txt
new file mode 100644
index 0000000..5641475
--- /dev/null
+++ b/e.txt
@@ -0,0 +1 @@

能够看到,当前你的本地仓库和upstream的区别是。。你改了c文件而upstream加了e文件。。

你从新rebase
➜  nocrazy git:(master) $ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Applying: [nocrazy-1] fix c.
➜  nocrazy git:(master) $ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 2 and 1 different commit each, respectively.
  (use "git pull" to merge the remote branch into yours)
nothing to commit, working directory clean
➜  nocrazy git:(master) $


这时和第一次有所不同, 

➜  nocrazy git:(master) $ git log --oneline
8c4c4b6 [nocrazy-1] fix c.
fd2e641 this is e
380a8dd this is d
e63667b this is c
11f5850 this is b
1cbdb56 this is a

查看一下有什么不同
➜  nocrazy git:(master) $ git diff ..origin/master
diff --git a/e.txt b/e.txt
deleted file mode 100644
index 5641475..0000000
--- a/e.txt
+++ /dev/null
@@ -1 +0,0 @@
-this is e
是由于你本身的远程仓库没有包含e文件。。。按照提示。 你须要作一次pull
可是pull会产生分支 。。
尝试一下而后立马撤销(http://stackoverflow.com/questions/1223354/undo-git-pull-how-to-bring-repos-to-old-state)

➜  nocrazy git:(master) $ git pull
Merge made by the 'recursive' strategy.
➜  nocrazy git:(master) $ git log --oneline
9d7a324 Merge branch 'master' of https://git.oschina.net/uniquejava/nocrazy
8c4c4b6 [nocrazy-1] fix c.
fd2e641 this is e
8530647 [nocrazy-1] fix c.
380a8dd this is d
e63667b this is c
11f5850 this is b
1cbdb56 this is a
➜  nocrazy git:(master) $ git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

可见, git pull生成的commit history多么的混乱!(相对于当前的origin/master, 
一会儿多出了3条commit history)
9d7a324 Merge branch 'master' of https://git.oschina.net/uniquejava/nocrazy
8c4c4b6 [nocrazy-1] fix c.
fd2e641 this is e

赶忙撤销并换成git rebase
➜  nocrazy git:(master) $ git show HEAD
commit 9d7a324e5e562475b9585ed029817fc98d09a1d4
Merge: 8c4c4b6 8530647
Author: cyper <345343747@qq.com>
Date:   Wed Aug 26 06:11:07 2015 +0800


    Merge branch 'master' of https://git.oschina.net/uniquejava/nocrazy
原来。。HEAD并非指向远程仓库的head..

➜  nocrazy git:(master) $ git show head
➜  nocrazy git:(master) $ git show HEAD
➜  nocrazy git:(master) $ git show master
➜  nocrazy git:(master) $ git show origin/master
。。。前三个信息都是指向本地仓库的头,是没一个commit id.最后一个是我想要的头,是我pull以前的commit id
因此有三种方法
git reset --hard HEAD^3
或git reset --hard origin/master
或者git reset --hard 8530647b .net

重作第7步。。
➜  nocrazy git:(master) $ git rebase upstream/master
First, rewinding head to replay your work on top of it...
Applying: [nocrazy-1] fix c.
➜  nocrazy git:(master) $ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 2 and 1 different commit each, respectively.
  (use "git pull" to merge the remote branch into yours)
nothing to commit, working directory clean
➜  nocrazy git:(master) $

如今由于本地仓库才是最新的。。你须要force push到origin而不须要理pull操做。。。
➜  nocrazy git:(master) $ git push origin master --force
Username for 'https://git.oschina.net': uniquejava
Password for 'https://uniquejava@git.oschina.net':
Counting objects: 6, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 569 bytes | 0 bytes/s, done.
Total 6 (delta 1), reused 0 (delta 0)
To https://git.oschina.net/uniquejava/nocrazy.git
 + 8530647...3e23afc master -> master (forced update)


git rebase产生了完美的commit history:
3e23afc [nocrazy-1] fix c.
fd2e641 this is e
380a8dd this is d
e63667b this is c
11f5850 this is b
1cbdb56 this is a

rem

相关文章
相关标签/搜索