|
|
| 第381行: |
第381行: |
| {| class="wikitable" | | {| class="wikitable" |
| |- | | |- |
| ! 命令 !! 说明 !! 示例 | | ! 命令 !! 说明 !! 备注 |
| |- | | |- |
| | '''<code>git log</code>''' | | | '''<code>git log</code>''' |
| | 查看版本提交历史 | | | 查看所有提交过的版本信息 |
| | | | | |
| <syntaxhighlight lang="PowerShell"> | | Note1: |
| Microsoft Windows [版本 10.0.19041.508]
| | # '''<code>git log --graph</code>''':查看分支commit关联拓扑图; |
| (c) 2019 Microsoft Corporation。保留所有权利。
| | # '''<code>git log --oneline</code>''':显示commit简略信息(只显示版本号前七位和提交时的备注信息); |
| | | #: 另'''<code>--pretty=oneline</code>'''(显示完整版本号和备注); |
| D:\git\eijux>git log
| | # '''<code>git log -5</code>''':显示过去5次提交; |
| commit 5e26159ad738b08b9321eba9ecaeff39c8acc42f (HEAD -> master, eijux/master)
| | # '''<code>git log --reverse</code>''':逆序显示commit; |
| Author: Eijux <chen@eijux.com>
| | # '''<code>git log --stat</code>''':显示commit历史,以及每次commit发生变更的文件; |
| Date: Fri Nov 1 01:18:47 2019 +0800
| | # '''<code>git shortlog -sn</code>''':显示所有提交过的用户,按提交次数排序; |
| | | Note2: |
| idea commit test 01<E7><82><B9>18<E5><88><86>
| | # '''<code>git log --author=<pattern></code>''':显示限定作者(正则表达式)的commit; |
| | | #: 另'''<code>--committer=<pattern></code>'''类似; |
| commit ffa14211ab7088d9782de019328238dcfe09a4bc
| | # '''<code>git log --since=<date></code>''':显示<date>之后的commit; |
| Merge: 3fbc79a fc32a4a
| | #: 另'''<code>--after=<date></code>'''、'''<code>--until=<date></code>'''、'''<code>--before=<date></code>'''类似; |
| Author: Eijux <chen@eijux.com>
| | |- |
| Date: Thu Oct 31 16:03:24 2019 +0800
| | | '''<code>git reflog</code>''' |
| | | | 查看所有分支的所有操作记录 |
| Merge branch 'master' of github.com:Eijux/eijux
| | | |
| | | <code></code> |
| commit 3fbc79ae2c8b7199c22133d1f3e4115848dbe749
| |
| Author: Eijux <chen@eijux.com>
| |
| Date: Thu Oct 31 04:19:09 2019 +0800
| |
| | |
| idea commit test
| |
| (END)
| |
| </syntaxhighlight> | |
| Note:
| |
| # '''<code>git log --graph</code>''':查看分支commit关联图; | |
| # '''<code>git log --pretty=oneline</code>''':只显示版本号和提交时的备注信息; | |
| |- | | |- |
| | '''<code>git blame</code>''' | | | '''<code>git blame</code>''' |
| 第419行: |
第409行: |
| | | | | |
| # '''<code>git blame <file></code>''':查看指定文件的修改记录; | | # '''<code>git blame <file></code>''':查看指定文件的修改记录; |
| |-
| |
| | '''<code>git reflog</code>'''
| |
| | 查看版本命令历史
| |
| |
| |
| <syntaxhighlight lang="PowerShell">
| |
| 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
| |
| </syntaxhighlight>
| |
| |} | | |} |
|
| |
|
常用操作
仓库
| 命令 |
说明 |
备注
|
git init
|
初始化Git仓库
|
git init:在当前目录初始化Git仓库
git init <newrepo>:在指定目录(<newrepo>)初始化Git仓库
|
git clone
|
克隆Git仓库
|
git clone <repo>:克隆仓库(<repo>)到当前目录
git clone -o<远程主机名> <repo>:克隆仓库(<repo>)当前目录,并为远程主机设置主机名
git clone <repo> <directory>:克隆仓库(<repo>)到指定目录(<directory>)
|
修改
| 命令 |
说明 |
备注
|
git add
|
将工作区新增或修改的文件添加到暂存区
|
git add [file1] [file2]:添加一个或多个文件到暂存区;
git add [dir]:添加指定目录到暂存区(包括子目录);
git add .:添加当前目录下的所有文件到暂存区;
git add -f [file]:强制添加存在于.gitignore的文件;
|
git commit
|
提交暂存区到本地仓库
|
git commit -m [message]:提交暂存区到本地仓库;
git commit [file1] [file2] -m [message]:提交暂存区的指定文件;
git commit ([file1] [file2]) -am [message]:直接提交(跳过git add);
|
git status
|
查看仓库当前的状态,显示有变更的文件
|
Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git status
On branch master
Your branch is up to date with 'eijux/master'.
Changed not staged for commit:
(use "git add <file>..." to include in what will be committed)
(use "git restore --staged <file>..." to unstage)
new file: 1.txt
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: 2.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
3.txt
- Changed not staged for commit:修改文件,未add
- Changes to be committed:修改并add,未commit
- Untracked files:新增文件,从未add
|
git diff
|
比较文件的不同,即暂存区和工作区的差异
|
git diff ([file]):查看暂存区和工作区的改动;
git diff --cached ([file]):(或git diff --staged ([file]))暂存区和上一个commit的差异;
git diff HEAD ([file]):查看工作区与当前分支最新commit之间的差异;
git diff [branchName] [file]:当前分支的文件与[branchName]分支的文件进行比较;
git diff [commitId] [file]:当前分支的文件与[commitId]提交的文件进行比较;
git diff --stat:显示摘要而非整个diff;
git diff [first-branch]...[second-branch]:查看两次提交之间的差异;
|
git stash
|
保存工作现场
|
git stash list:查看所有保存的工作现场;
git stash apply <stash>:恢复stash(但不删除);
git stash drop <stash>:删除stash;
git stash pop <stash>:恢复并删除stash;
- <stash>形如“stash@{0}”,可在list中看到:
- e.g.
git stash pop stash@{0}
|
git reset
|
回退版本
|
git reset [--soft | --mixed | --hard] [HEAD]
关于参数:
--soft:将HEAD指向指定commit(这使得所有更改的文件都“等待提交”);
--mixed:(默认)重置索引,但不重置工作树(保留更改的文件,标记为:未提交?未add?);
--hard:重置索引和工作树(自<commit>以来对工作树中跟踪文件的任何更改都将被丢弃);
--merge:重置索引,并
- 1、在工作树中更新‘<commit>与HEAD不同’的文件,
- 2、在工作树中保留‘索引与工作树不同’的文件(即,未add的更改)。
- 如果‘<commit>和索引不同’的文件具有未暂存的更改,则会中止重置。
--keep:重置索引,并
- 1、在工作树中更新‘<commit>与HEAD不同’的文件。
- 如果‘<commit>与HEAD不同’的文件具有本地修改,则会中止重置。
- 参考Documentation:Reset的DISCUSSION一节
关于[HEAD]:
- 当前版本:
HEAD^或HEAD~0
- 上一个版本:
HEAD^或HEAD~1
- 上上一个版本:
HEAD^^或HEAD^2
- 上上上一个版本:
HEAD^^^或HEAD^3
- 以此类推
版本回退:
git reset --hard HEAD^:回退到上一次commit;
git reset --hard <commitID>:回退到指定commit之前;
|
git revert
|
撤销操作
|
- revert是将需要的版本内容反向修改回去,并提交一个新版本;
git revert HEAD:撤销前一次 commit;
git revert HEAD^:撤销前前一次 commit;
git revert <commitID>:撤销指定的版本;
|
git restore
|
文件恢复
(Git 2.23引入)
|
Note1:
git restore [<options>] [--source=<tree>] [--staged] [--worktree] [--] <pathspec>
[--source=<tree>]:指定还原源:
- 默认(不设置)从索引恢复内容;
- 若指定
--staged,则从HEAD恢复内容;
[--staged] [--worktree]:指定恢复目标:
- 默认(不设置)恢复到工作树的内容;
--staged:用于恢复索引的内容;
--staged --worktree:用于同时恢复索引和工作区的内容;
- 注意:使用“还原源”中的某些内容还原“工作树指定路径”:如果“工作树被跟踪路径”不存在与还原源中,则将删除该路径以匹配源;
Note2:
git restore --staged <file>:从HEAD恢复<file>到索引,
- 等效于
git reset <file>;
git restore --source=HEAD --staged --worktree <file>:从HEAD恢复<file>到索引和工作树,
- 等效于
git checkout -- <file>;
|
git mv
|
移动或重命名工作区文件
|
git mv -f [file] [newfile]:强制执行;
|
git rm
|
删除工作区文件
|
git rm <file>:将文件从暂存区和工作区中删除;
git rm --cached <file>:将文件从暂存删除,工作区保留(即停止追踪指定文件,通常是在文件曾经被git管理过,现在不需要被git接管的时候使用);
git rm -r *:递归删除;
git rm -f <file>:强制删除;
|
关于撤销工作区修改
- 若工作区修改未add到stage:
git checkout -- <file>
- 若工作区修改已add,但未commit:
git reset HEAD <file>(1、从版本库commit中恢复到stage)
git checkout -- <file>(2、撤销工作区修改)
分支
| 命令 |
说明 |
备注
|
git branch
|
分支命令
|
git branch:查看所有本地分支
git branch -r:查看所有远程分支
git branch -a:查看本地和远程的所有分支
git branch <branchname>:创建<branchname>分支
git branch -d <branchname>:删除<branchname>分支
git branch -D <branchname>:强制删除一个未被合并过的分支<branchname>
git branch --set-upstream <本地分支名> <远程主机名>/<远程分支名>:手动在本地分支与远程分支间建立追踪关系;
|
git checkout
|
签出分支(或文件)
|
分支:
git checkout <branchname>:切换到<branchname>分支
git checkout -b <branchname>:创建并切换到<branchname>分支
git checkout -b <本地新建分支> <远程主机名>/<远程分支>:在远程分支基础上新建本地分支(先有远程主机信息git fetch <远程主机名> <远程分支>)
- 切换分支的时候,Git会用该分支最后提交的快照替换本地工作目录的内容。
文件:
git checkout [<options>] [<branch>] -- <file>
git checkout -- <file>:从当前分支签出文件(即撤销工作区文件<file>的修改);
- 工作区修改,但未add到暂存区:checkout重置到与版本库一致
- 工作区修改并add后,再次修改:checkout重置到与暂存区一致
git checkout <commit> -- <file>:从指定commit签出文件;
git checkout <branch> -- <file>:从指定分支签出文件;
git checkout -- *.xxx:签出所有xxx后缀的文件;
git checkout -- xxx/:签出所有xxx目录的文件;
|
git merge
|
分支合并
|
Note1:
- 合并分支并产生新的提交;
- 不会改变当前分支的开始位置;
- 只处理一次冲突;
- 引入了一次合并的历史记录,合并后的所有 commit 会按照提交时间从旧到新排列;
- 合并后分支过程信息更多更复杂,可能会提高之后查找问题的难度;
Note2:参数
- (N = 被合并分支中,需要合并的commit个数)
- (主分支和被合并分支中,被合并的commitID并不相同,是重新提交,而非引用)
--ff:(默认)快速合并(主分支新增N个commit,冲突处理则N+1);
- 如果合并过程出现冲突,Git会显示出冲突并等待手动解决;
--ff-only:只有能快速合并的情况才合并(主分支新增N个commit);
- 如果合并过程出现冲突,Git会自动abort此次merge;
--no-ff:不使用快速合并(主分支新增N+1个commit,冲突处理则N+2);
- 会额外生成一次新的提交记录,用于标识此处进行了一次merge操作(需使用
-m <message>记录提交信息);
--squash:压缩合并(主分支新增1个commit);
- 将待合并的分支的内容压缩成一个新的提交合并进来;
Note3:
git merge <branch1>:将<branch1>分支合并到当前分支;
- 将branchB和并到branchA:切换到branchA中执行“
git merge branchB”。
git merge <branch1> <branch2> <branch3> <branch4>:合并多个分支到当前分支;
|
git rebase
|
分支(变基)合并
|
Note1:
- (变基)合并分支但并不产生新的提交;
- 改变了当前分支的开始位置;
- 可能会有多次冲突处理;
- 没有多余的合并历史的记录,且合并后的 commit 顺序不一定按照 commit 的提交时间排列;
- 合并后分支上每个 commit 点都是相对独立完整的功能单元;
Note2:
git rebase <branch1>:
git rebase --continue:(解决完冲突并git add后)继续应用(apply)余下的补丁进行合并;
git rebase --abort:终止rebase的行动,并将分支回退到rebase开始前的状态;
|
git cherry-pick
|
复制commit
|
Note1:
git cherry-pick <commit>:是将指定的提交(commit)应用于当前分支,这会在当前分支产生一个新的提交;
git cherry-pick <branch>:表示应用该分支的最新提交,到当前分支;
Note2:
- 复制多个commit时,当前分支会产生多个对应的commit。
git cherry-pick <commitA> <commitB> <commitC>:复制多个commit;
git cherry-pick <commitA>...<commitC>:(不包括<commitA>)复制从<commitA>到<commitC>的多个commit(<commitA>必须在<commitC>之前);
-
git cherry-pick <commitA>^...<commitC>:(包括<commitA>)复制从<commitA>到<commitC>的多个commit(同上);
- cherry-pick 也支持转移另一个代码库的提交,方法是先将该库加为远程仓库,再抓取代码并获取<commitID>
Note3:
git cherry-pick --continue:用于解决代码冲突后,让cherry-pick过程继续执行(先将修改的文件加入暂存区git add);
git cherry-pick --abort:发生代码冲突后,放弃cherry-pick过程,恢复到操作前状态;
git cherry-pick --quit:发生代码冲突后,放弃cherry-pick过程,但不恢复状态;
|
git switch
|
切换分支
(Git 2.23引入)
|
与git checkout分支等效:
git switch <branch>分支:等效于git checkout <branch>;
git switch -c <branch>分支:(--create)等效于git checkout -b <branch>分支;
|
冲突合并:
冲突合并涉及文件添加、移除的操作,还包括文件修改内容的合并。
远程
| 命令 |
说明 |
备注
|
git remote
|
管理远程仓库主机名
|
git remote -v:显示所有远程仓库
git remote show [remoteName]:显示远程仓库的信息
- 如:git remote show origin
git remote add [remoteName] [url]:添加关联远程版本库
- 如:git remote add origin git@github.com:tianqixin/runoob-git-test.git
git remote rm [remoteName]:删除远程仓库
git remote rename [old_name] [new_name]:修改远程仓库名
|
git pull
|
下载远程代码并合并:
git pull <远程主机名> <远程分支名>:<本地分支名>
|
Note1:
- 合并到当前分支,可省略“
:<本地分支名>”;
- 等效于
git fetch+git merge FETCH_HEAD(概念上等效,实现上不一样???)。
Note2:
git pull --rebase <远程主机名> <远程分支名>:<本地分支名>:合并需要采用rebase模式的pull;
git pull -p:若服务器删除了某分支,拉取远程分支的时候,同步删除本地的该分支;
- 等同于:
git fetch --prune <远程主机名> 、git fetch -p;
Note3:
git pull <远程主机名> <远程分支名>
- 拉取远程主机的分支,并与本地当前分支合并;
git pull <远程主机名>
- 拉取远程主机的对应分支,并与本地当前分支合并(当前分支与远程分支必须存在追踪关系);
git pull
- 拉取远程主机的对应分支,并与本地当前分支合并(当前分支只有一个追踪分支);
|
git push
|
上传远程代码并合并:
git push <远程主机名> <本地分支名>:<远程分支名>
|
Note1:
git push --delete:删除远程主机的分支;
git push --force:(慎用)强制推送,忽略远程分支版本比本地高(应先pull);
git push --all:无论对应远程分支是否存在,将本地的所有分支都推送到远程主机;
git push --tags:推送所有未推送过的本地标签;
git push <tag>:推送本地标签<tag>;
Note2:
git push -u <远程主机名> <本地分支名>
- 如果当前分支与多个主机存在追踪关系,则可以使用-u参数指定一个默认主机,这样后面就可以不加任何参数使用git push;
git push <远程主机名> <本地分支名>
- 表示将本地分支推送到与之存在追踪关系的远程分支(通常两者同名),如果该远程分支不存在,则会被新建;
git push <远程主机名> :<远程分支名>
- 表示删除对应的远程分支(推送空的本地分支到远程);
git push <远程主机名>
- 表示将当前分支推送到远程主机的对应分支(当前分支与远程分支必须存在追踪关系);
git push
- 表示将当前分支推送到远程主机的对应分支(当前分支只有一个追踪分支);
Note3:关于推送方式
- simple方式:不带任何参数的
git push,默认只推送当前分支;(默认)
- matching方式:推送所有有对应的远程分支的本地分支;(Git 2.0之前默认)
git config中的push.default可配置推送方式;
|
|
git fetch
|
获取远程主机的版本库更新(commit):git fetch [alias] [branch]
Download objects and refs from another repository
|
Note1:
- FETCH_HEAD:是一个版本链接,记录在本地的文件中(.git/FETCH_HEAD),指向着目前已经从远程仓库取下来的分支的末端版本;
- “git fetch”将:
- 更新“git remote”中所有远程仓库所包含分支的最新commit-id, 将其记录到“.git/FETCH_HEAD”文件中;
- 下载内容到“.git\objects”及“.git\refs”;
git fetch 与 git pull:
git fetch拉取更新信息(commitID),但不会合并到本地工作目录;
git pull将本地库更新至远程库的最新状态;
Note2:
git fetch <远程主机名> <远程分支1> <远程分支2> <远程分支3>:从远程仓库拉取多个分支;
git fetch <远程主机名> <远程分支>:拉取指定主机指定分支的更新;
git fetch <远程主机名>:拉取指定主机的更新(不指定分支时通常默认为master);
git fetch :拉取所有分支(branch)的更新;
Note3:
- 拉取分支更新,并在本地新建分支:
git fetch <远程主机名> <远程分支>:<本地新建分支>
- (
git fetch <远程主机名> <远程分支>)
git checkout -b <本地新建分支> <远程主机名>/<远程分支>
- 拉取远程分支更新,并合并到本地分支(与
git merge配合使用):
git fetch origin master:从origin拉取分支master的更新;
git merge origin/master:合并origin/master分支到当前分支;
- 拉取多分支更新:
- 拉取多个分支:
git fetch origin master stable oldstable,从远程仓库origin拉取master、stable、oldstable分支的更新;
- 合并多个分支:
git merge origin/master hotfix-2275 hotfix-2276 hotfix-2290,合并origin/master、origin/stable、origin/oldstable到当前分支。
|
日志
| 命令 |
说明 |
备注
|
git log
|
查看所有提交过的版本信息
|
Note1:
git log --graph:查看分支commit关联拓扑图;
git log --oneline:显示commit简略信息(只显示版本号前七位和提交时的备注信息);
- 另
--pretty=oneline(显示完整版本号和备注);
git log -5:显示过去5次提交;
git log --reverse:逆序显示commit;
git log --stat:显示commit历史,以及每次commit发生变更的文件;
git shortlog -sn:显示所有提交过的用户,按提交次数排序;
Note2:
git log --author=<pattern>:显示限定作者(正则表达式)的commit;
- 另
--committer=<pattern>类似;
git log --since=<date>:显示<date>之后的commit;
- 另
--after=<date>、--until=<date>、--before=<date>类似;
|
git reflog
|
查看所有分支的所有操作记录
|
|
git blame
|
查看文件记录
|
git blame <file>:查看指定文件的修改记录;
|
标签
tag实际就是一个指向commit的指针,将一个有意义的tag名称与commit相关联。
git标签有两种类型:
- 轻量级的(lightweight):实际上它就是个指向特定提交对象的引用。
- 含附注的(annotated):
实际上是存储在仓库中的一个独立对象,有自身的校验和信息,包含标签名称,电子邮件地址和日期,及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。
| 命令 |
说明 |
备注
|
git tag
|
git标签
|
Note:
git tag:查看所有标签;
git tag <tagname>:创建标签(默认指定到当前分支);
git tag <tagname> <commitID>:创建标签,并关联到指定分支;
git tag -a <tagname>:创建带注解的标签(Git会打开编辑器来编辑tag的注解信息);
git tag -d <tagname>:删除标签;
git show <tagname>:查看tag关联的commit信息
git tag -a <tagname> -m "标签信息":指定标签信息
git tag -s <tagname> -m "标签信息":PGP签名标签
如:
Microsoft Windows [版本 10.0.19041.508]
(c) 2019 Microsoft Corporation。保留所有权利。
D:\git\eijux>git tag
D:\git\eijux>git tag rc1.0
D:\git\eijux>git tag -a rc2.0
# Write a message for tag:
# rc2.0
# Lines starting with '#' will be ignored.
D:\git\eijux>git tag rc3.0 ffa1
D:\git\eijux>git log --decorate
commit 5e26159ad738b08b9321eba9ecaeff39c8acc42f (HEAD -> master, tag: rc2.0, 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 (tag: rc3.0)
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
D:\git\eijux>git show rc3.0
commit ffa14211ab7088d9782de019328238dcfe09a4bc (tag: rc3.0)
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
D:\git\eijux>
|
命令辨析
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 FETCH_HEAD的缩写。
更准确地说,git pull使用给定的参数运行git fetch,并调用git merge将检索到的分支头合并到当前分支中。 使用--rebase,它运行git rebase而不是git merge。
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”的对象;
- 本地文件与分支的关系?
.git\refs\head\ [本地分支]
.git\refs\remotes\ [正在跟踪的分支]
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---------┘
|
关于rebase的过程
| rebase的过程
|
|
左图:
- “
git rebase origin”会把“mywork”分支里的所有提交(commit)取消掉,并临时保存为补丁(位于“.git/rebase”);
- 然后把“mywork”分支更新为到“origin”分支末尾,最后把保存的这些补丁应用到“mywork”分支上。
- (老的commit会被丢弃,并在git gc发生时被删除?)(参见:图解git rebase 与merge的区别)
|
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开始前状态。
The Golden Rule of Rebasing rebase
never use it on public branches(不要在公共分支上使用)
| rebase的过程
|
|
如左图,执行git checkout feature与git rebase master,rebase将master所有commit移动到feature之后:
- 分支历史与其他master分支使用者的产生分歧;
- master的分支历史追踪变得极为困难,不利于问题排查;
所以,在公共分支、需要保留历史的分支,不应该使用rebase!
|
reset 与 revert
reset 与 revert 都是进行“撤销”操作,但其效果并不相同:
| reset |
revert
|
- 直接删除指定的commit。(就像从没有发生过一样,即撤销了操作)
|
- 提交新版本,将需要revert的版本内容反向修改回去。(提交新的commit来“纠正”修改,即撤销了修改)
- 之前的commit和history都会保留;
- 版本会递增,不影响之前提交的内容;
|
对于分支merge的撤销操作(如将“eijux”合并到“master”):
- reset:
- reset之后与merge之前一样,两个分支未被合并,且没有merge的操作历史;
- revert:
- revert之后,分支合并状态不变,并有merge操作的历史,但“master”的内容与merge之前一致,;
- (即只是撤销了“eijux”合并到“master”所修改的“master内容”,merge操作仍然有效)
|
reset、revert与checkout
|
|
Commit-level
|
File-level
|
checkout
|
git checkout <commit/HEAD^?>:
- 移动HEAD到另外一个分支(或commit),并更新工作目录。
|
git checkout <commit/HEAD^?> <file>:
- 将worktree文件<file>重置到指定commit的版本(将丢弃工作区文件<file>未add的修改)。
|
reset
|
git reset [--soft/--mixed/--hard] <commit/HEAD^?>:
- 将分支的指向其他commit,以进行版本回退(被跳过的commit成了dangling commit,将在下次git垃圾回收被删除)。
|
git reset <commit/HEAD^?> <file>:
- 将stage文件<file>重置到指定commit的版本。
- (
[--soft/--mixed/--hard]对此不起作用,stage总会被更新, worktree不会被更新)
|
revert
|
git reset <commit/HEAD^?>:
- 通过新建commit进行反向修改,以实现撤销某个commit的修改。
|
|
log 与 reflog
| log |
reflog
|
|
显示所有提交过的版本信息
|
查看所有分支的所有操作记录
|
|
对于已经被删除的commit记录和reset的操作:git log则没有相关的commit信息,git reflog则可以看到与commit相关的操作记录;
|
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
|