-
git merge --help
:打开查看git merge
的本地说明文档 -
假设git 的HEAD引用指向当前分支master(
HEAD->master->commit_1
),通过git branch dev
新建一个指向当前commit_1
的dev分支(HEAD->master->commit_1,dev->commit_1
),通过git checkout dev
切换到dev
分支(HEAD->dev->commit_1,master->commit_1
),git checkout
会将当前工作区内容全部替换为新分支dev
的当前提交commit_1
,由于这里两个分支都指向同个commit
,所以工作区切换后内容是不变的。两个命令合并一步到位:git checkout -b dev
,这里的-b
是-branch
也就是checkout一个新分支的意思。 -
假设
commit_1
的上一个提交记录是commit_0
。1、如果想要HEAD指向commit_0
,可以通过git checkout commit_0
实现(HEAD->commit_0,master->commit_1
)。2、如果想要HEAD回退n个提交记录,可以使用git checkout HEAD~n
实现,这时候HEAD指向前n个提交记录,当前工作区也相应回退,处于detached HEAD(脱离HEAD)的状态。3、在HEAD回退到前n个提交记录节点后,可以通过git branch bugfix
在当前提交记录节点新建bugfix分支,然后通过checkout切换到工作区进行修改。
- (这条说下git reset) 把已经git add添加到暂存区的文件回退到untrack状态(从暂存区回退到工作区):
git reset HEAD <文件>
,但是原理是什么?
git reset <--hard|--soft|--mixed> <commit_n|HEAD|HEAD~n|branch_n>
–hard:1、把当前分支指向提交记录节点commit_n(HEAD->master->commit_n
),2、并用commit_n的提交记录节点的内容覆盖暂存区index(这时暂存区还原为commit_n时候的状态),3、同时把暂存区的这种还原的动作同步到工作区(如果工作区有文件从并未add到暂存区,那么这些文件在暂存区不存在任何还原动作,也就不会收到“同步”动作的影响,因为暂存区从来没发现它
)
–mixed(默认):1、把当前分支指向提交记录节点commit_n(HEAD->master->commit_n
),2、并用commit_n的提交记录节点的内容覆盖暂存区index(这时暂存区还原为commit_n时候的状态)(这时工作区相对于commit_n的所有改动都被标识为未add状态)
–soft:1、把当前分支指向提交记录节点commit_n(HEAD->master->commit_n
)(这时暂存区相对于commit_n的所有改动都被标识为未commit状态)
所以git reset HEAD <文件>
就是把提交记录覆盖暂存区,相当于撤销add到暂存区的动作
git rm --cached nihao.txt
用来删除index暂存区的记录,文件被追踪为unstaged状态- 暂存区已追踪记录的文件,不想被追踪到它的更改,可以用
git update-index --assume-unchanged java.txt
,用git update-index --no-assume-unchanged java.txt
恢复追踪 - 把本地仓库的提交记录file覆盖回暂存区file:
git reset HEAD file
- 把暂存区一个或者多个文件(可以用*表示全部)覆盖回工作区:
git checkout -- <file>...
git branch <branch> [<start point>]
新建一个分支,指向一个commitgit branch -f <branch> [<start point>]
新建一个分支,不管分支名是否存在,存在则覆盖git checkout commit_n/branch file
把某个提交版本的file覆盖到工作区git stash <list|push|pop|apply|drop|clear>
:<查看所有|存储当前并清空暂存区工作区|弹出顶部一个|应用但不删除顶部一个|删除顶部一个|清空所有>
工作中常用的命令
-
git clone -b dev git@github.com:lwr/csms.git
把远程的dev分支
拉取到本地的新建dev分支
-
git checkout -b local_dev
在本地的dev分支
基础上新建一个用于开发的local_dev分支
-
需要提交本地修改到远程dev分支,先切换回本地的
dev分支
,通过git fetch origin dev
更新远程分支origin/dev
,通过git diff origin/dev
对比远程分支和当前分支,查看是否远程分支有人提交了修改。
1、如果远程存在修改,通过git merge origin/dev
合并远程的更新。然后通过git merge local_dev
再合并本地的开发修改。然后git push origin dev:dev
把本地的dev推送到远程的dev
2、如果远程不存在修改,通过git merge origin/dev
合并远程的更新。然后通过git merge(rebase) local_dev
合并本地的开发修改。然后git push origin dev:dev
把本地的dev推送到远程的dev -
git fetch origin master:temp
把远程主机origin的master分支拉取到本地新创建的temp分支 -
git branch <-d|-D> temp
合并temp后,用此命令删除temp分支 -
git commit --amend [-m ""]
用本次提交覆盖上次的提交记录(上次版本号commit会更新为本次的)
git merge
产生冲突后,去到冲突文件修改,然后git add,然后执行git commit表示解决冲突merge成功(自动生成一条merge的提交log)git merge --squash branch
把需要合并的分支的所有提交记录覆盖为一个,如果不想把合并分支的零散提交记录放进当前分支,可用此参数。git rebase
产生冲突后,修改冲突,使用git add提交,然后不要commit,使用git rebase --continue
来完成最终的rebase。如果不想解决冲突,可以直接git rebase --abort
来回到之前的两个分支的状态。git rebase 分支1 [分支2]
:
1、git rebase 分支1
:分为三步:第一,倒退回到分支1的顶部;第二,从分支1顶部重做当前分支节点(与分支1共同祖先节点除外);第三,移动当前分支到重做后的顶部节点。
2、git rebase 分支1 分支2
:(给定分支2参数后,重做与当前所在分支无关了。)分为三步:第一,倒退回到分支1的顶部;第二,从分支1顶部重做分支2节点(与分支1共同祖先节点除外);第三,移动当前分支到重做后的顶部节点。
-
git log --graph [--oneline]
以节点树的形式查看日志 -
git merge --no-ff branch
如果当前的分支在合并分支的一个历史节点上,不加–no-ff会快速把当前分支指针移动到需要合并分支的节点上,带来的问题是如果需要回退到HEAD^
,是回退到合并分支的HEAD^
,因为提交记录节点被合并了。加上此参数,会额外创建一个merge节点,从而能够找到合并前一个节点。 -
git revert -n commit_n
:把commit_n
节点的提交内容反做
,比如一个commit1到commit5的提交,我想撤销commit3的提交,可以用revert命令来反做,-n参数表示反做后不立即提交commit6版本记录,需要手动commit。所谓反做一个提交记录,就是单单撤销这个提交记录所做的修改。 -
git cherry-pick commit1 commit3 commit2
:因为所谓的提交记录其实就是修改记录,cherry-pick
命令就是可以随意地不按顺序地从历史提交记录中选择一个或者多个记录,把这些记录所做地修改重新在当前HEAD节点再应用一次,因此会生成相应地一个或者多个新地提交节点。 -
git rebase -i HEAD~n
:在HEAD~n
节点上rebase当前分支,通过打开vim,修改pick节点顺序,或者删除节点,保存后当前分支指向一个新的rebase分支。(类似于cherry-pick) -
git tag v1 commit_n
:打标签,标签不可以移动
#创建 branchname分支 和 远程仓库分支upstream 的追踪(track)关系
#因此upstream被认为是本地branchname的远程追踪分支
#如果branchname没有指定(缺省),默认branchname为当前所在分支
git branch -u upstream branchname(ps: git branch -u origin/dev dev)
git branch --set-upstream-to=upstream branchname
#Remove the upstream information for <branchname>.
#If no branch is specified it defaults to the current branch.
git branch --unset-upstream branchname