Git:命令辨析
跳到导航
跳到搜索
pull 与 fetch
More precisely, git pull runs git fetch with the given parameters and calls git merge to merge the retrieved branch heads into the current branch. With --rebase, it runs git rebase instead of git merge. 更准确地说,git pull 使用给定的参数运行 git fetch ,并调用 git merge 将检索到的分支头合并到当前分支中。 带有 --rebase 时,它运行 git rebase 而不是 git merge。 即,在默认模式下,git pull 是 git fetch 后跟 git merge FETCH_HEAD 的缩写。
fetch 理解
- fetch 是否有下载?
- 当然有下载,拉取的更新内容保存在“.git\objects”及“.git\refs”中,只是没有合并到当前的工作区,所以没有直观的改变;毕竟merge是不会有下载操作的。
- fetch 更新的是什么内容?
- fetch 会下载远程分支
orign/master
的文件存储对象到.git\objects
; - fetch 会更新
FETCH_HEAD
文件(如:5e26159ad738b08b9321eba9ecaeff39c8acc42f branch 'master' of github.com:Eijux/eijux
),其中commit_ID对应.git\objects
的对象;
- fetch 会下载远程分支
- 本地文件与分支的关系?
.git\refs\head\ [本地分支] .git\refs\remotes\ [正在跟踪的分支]
使用
- 当本地没有新的修改时:
- 使用 fetch 获取远程分支;
- 重新 checkout 该分支。【???或许是这样】
- 当本地有新修改(未 commit 的修改、未 push 的 commit)时:
- 必须保证工作区没有修改;
- 可将修改的内容:1、提交为新的 commit;2、保存到 stage;
- 使用 pull 拉取远程分支并合并(merge 或 rebase);
- 解决合并冲突(如果有),并在本地提交;
- 通过 push 推送本地分支到远程。
- 必须保证工作区没有修改;
merge 与 rebase
merge 与 rebase 同为合并分支,但是还是有区别的:
merge | rebase |
---|---|
产生新的提交 | 没有新提交,但会合并之前的commit历史 |
不改变当前分支的开始位置 | 改变了当前分支的开始位置 |
只处理一次冲突 | 可能会有多次冲突处理 |
合并后的所有 commit 会按照提交时间从旧到新排列 | 合并后的 commit 顺序不一定按照 commit 的提交时间排列 |
合并后分支过程信息更多更复杂 | 合并后分支上每个 commit 点都是相对独立完整的功能单元 |
执行过程:merge
merge的过程 | |
---|---|
以左图为例, “ git merge origin ”将两个分支的最新commit的内容进行合并,进行冲突处理之后作为新的commit提交到“mywork”分支:
| |
git logg查看commit时,其顺序为:(有时间顺序)
C1-----C2-----C3-----C4-----C7 └-------C5-----C6---------┘ |
什么是“Fast-forward”?
Fast-forward,即“快速合并”: 由于你想要合并的分支 hotfix 所指向的提交 C4 是你所在的提交 C2 的直接后继, 因此 Git 会直接将指针向前移动。——换句话说,当你试图合并两个分支时, 如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
示例:
执行过程:rebase
rebase的过程 | |
---|---|
左图:
| |
git logg查看commit时,其顺序为:(C5、C6未按时间顺序)
C1-----C2-----C3-----C4-----C5-----C6 |
关于rebase的冲突
rebase过程中可能出现多次冲突,Git会停止rebase来进行冲突解决;
- 在解决冲突后,用" git add "命令去更新这些内容的索引(无需执行
git commit
); - 执行“
git rebase --continue
”继续rebase过程;
- 在rebase过程的任何时候,都可以用“
git rebase --abort
”来终止rebase,并且将分支回退到rebase开始前状态。
使用
对于: git checkout branchA git merge branchB 是将 B 合并到 A git rebase branchB 是将 A 变基到 B(将A中的commit重新提交到B???但是IDEA文档中说的好像相反)
示例:
- merge:将 hotfix 合并到 master
- rebase:将 experiment 变基到 master
The Golden Rule of Rebasing rebase
never use it on public branches(不要在公共分支上使用)
rebase的过程 | |
---|---|
如左图,执行
所以,在公共分支、需要保留历史的分支,不应该使用rebase! |
reset、revert与checkout
Commit-level | File-level | |
---|---|---|
checkout
|
|
|
reset
|
|
|
revert
|
|
撤销commit:reset 与 revert
reset 与 revert 都是进行“撤销”操作,但其效果并不相同:
reset | revert |
---|---|
|
|
对于分支merge的撤销操作(如将“eijux”合并到“master”):
|
log 与 reflog
log | reflog |
---|---|
显示所有提交过的版本信息 |
查看所有分支的所有操作记录 |
对于已经被删除的 | |
Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git log
commit 5e26159ad738b08b9321eba9ecaeff39c8acc42f (HEAD -> master, tag: rc1.0, eijux/master)
Author: Eijux <chen@eijux.com>
Date: Fri Nov 1 01:18:47 2019 +0800
idea commit test 01<E7><82><B9>18<E5><88><86>
commit ffa14211ab7088d9782de019328238dcfe09a4bc
Merge: 3fbc79a fc32a4a
Author: Eijux <chen@eijux.com>
Date: Thu Oct 31 16:03:24 2019 +0800
Merge branch 'master' of github.com:Eijux/eijux
commit 3fbc79ae2c8b7199c22133d1f3e4115848dbe749
Author: Eijux <chen@eijux.com>
Date: Thu Oct 31 04:19:09 2019 +0800
idea commit test
commit fc32a4a8e24b963097f088a975d05ffa68f0c0bb
Author: Eijux <chen@eijux.com>
Date: Wed Oct 30 05:13:47 2019 +0800
add gitignore file
...
(END)
|
Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git reflog
5e26159 (HEAD -> master, eijux/master) HEAD@{0}: pull eijux master: Fast-forward
fc32a4a HEAD@{1}: commit: add gitignore file
d07be0a HEAD@{2}: commit: branch management test
492be10 HEAD@{3}: merge dev: Merge made by the 'recursive' strategy.
fc1038b HEAD@{4}: checkout: moving from dev to master
9d0f76e (dev) HEAD@{5}: commit: write a line on branch dev
7640602 (eijux/dev) HEAD@{6}: checkout: moving from master to dev
fc1038b HEAD@{7}: reset: moving to HEAD
fc1038b HEAD@{8}: commit: branch back to master
7640602 (eijux/dev) HEAD@{9}: merge dev: Fast-forward
63fa5ac HEAD@{10}: checkout: moving from dev to master
7640602 (eijux/dev) HEAD@{11}: commit: add dev branch
63fa5ac HEAD@{12}: checkout: moving from master to dev
63fa5ac HEAD@{13}: pull eijux master --allow-unrelated-histories: Merge made by the 'recursive' strategy.
da60d32 HEAD@{14}: commit: add t5.txt
e88cb69 HEAD@{15}: commit: delete rmtest.txt
cc1e40c HEAD@{16}: commit: changed t4 and add t5
1707196 HEAD@{17}: commit: changed t4
378fb5a HEAD@{18}: commit: add t4.txt
e3501ab HEAD@{19}: commit: add t4
ea463d0 HEAD@{20}: commit: add t2.txt
92ad079 HEAD@{21}: commit: git commit single file test
061529e HEAD@{22}: reset: moving to 061529
69e722f HEAD@{23}: reset: moving to head
69e722f HEAD@{24}: reset: moving to head^
061529e HEAD@{25}: reset: moving to 061529
69e722f HEAD@{26}: reset: moving to 69e722
061529e HEAD@{27}: commit: git diff test
69e722f HEAD@{28}: commit: banben test
fd1fd5f HEAD@{29}: commit (initial): git add test
|