一、rebase命令
1、git rebase origin/master 基于远程仓库的master分支rebase当前分支代码
2、git rebase -i origin/master -i参数可进入到交互窗口来操作commit
3、git rebase -i HEAD~4 此时会合并最近4个提交记录,数字可修改
4、git rebase -i commitid 此时会合并commitid之后的提交记录(不包括该commitid的提交记录)。commitid可以通过git log来进行查看
案例一:
场景:基于dev分支有两个开发分支。feature分支和hotfix分支。假如hotfix合入了dev分支。此时dev分支已经领先了feature基于的dev分支,我们需要同步dev分支的改动。
解决方案:merge、rebase。 merge: git merge dev 切换到feature分支,使用git merge dev。出现的问题:可能需要解决冲突;并且会有一个merge记录,扰乱commit的提交记录。因此使用rebase rebase: (1)git pull --rebase origin dev 在自己当前分支上进行rebase操作,且当前分支是基于dev分支开发的 (2)git rebase --continue rebase过程中可能会出现confict、我们需要解决冲突,然后git add ./保存修改,然后执行continue命令保存。 (3)git rebase --abort 使用--abort参数来终止rebase的行为,然后该分支会回到rebase开始前的状态 解析rebase的操作: 首先,rebase会把featrue分支的每个commit取消掉。 其次,把上面的操作临时保存为patch文件,存在.git/rebase目录下。 然后,把feature分支更新到最新的dev分支; 最后,把上面的patch文件应用到dev分支上
案例二:
如何将commit A分解为commit B、commit C (1)首先使用git rebase -i进入到操作页面,将commit A的pick修改为e (2)然后使用git reset --mixed HEAD~1将commit A提交的保存修改文件回退到work dirctery。 (3)分批次git add -u git commit -s生成commit B、commit C (4)最后git rebase --continue
备注:
调整好本地分支后,进行git push -f 会强制覆盖远程分支,使之与本地分支相同
git push origin zhanghl/binder-test:zhanghl/binder-test 将本地zhanghl/binder-test分支推送到远程zhanghl/binder-test分支。左侧(绿颜色)为本地分支,右侧(紫颜色)为远程分支
当前分支名字和远程分支名字不相同时,虽然能设置了关联,但是直接使用git push报错。提示使用git push origin HEAD:zhanghl/sendfile。
rebase冲突解决
1、git rebase --continue 解决冲突后,执行该命令可以保存修改为当前冲突commit
2、git rebase --abort 任何时候使用该命令来终止rebase操作。可以取消上次的rebase操作
二、关联本地分支到远程分支
git checkout --track origin/branch_name
本地会新建分支 branch_name ,自动跟踪远程的同名分支git push --set-upstream origin branch_name
自动在远程创建一个 branch_name 分支,然后本地分支会 track 该分支。后面再对该分支使用 push 和 pull 就自动同步git branch --set-upstream-to=origin/zhanghl/binder-test
将当前同名分支跟踪到远程分支/zhanghl/binder-test中git branch --set-upstream-to=origin/zhanghl/binder-test dev
将dev分支跟踪到远程分支/zhanghl/binder-test中,而不管当前分支是谁简写:
git branch -u origin/zhanghl/binder-test git branch -u origin/zhanghl/binder-test dev
三、修改分支名称
1、修改本地分支名称
git branch -m old_branch new_branch
修改本地分支名称
2、修改远程分支名称
(1)先删除远程分支feature/develop/today1:
git push origin --delete feature/develop/today1
(2)修改本地分支名称:feature/develop/today2,该命令操作时,当前分支不必切换到分支feature/develop/today1
git branch -m feature/develop/today1 feature/develop/today2
(3)切换当前分支为feature/develop/today2
git checkout feature/develop/today2
(4)将分支feature/develop/today2推送(强制覆盖)至远程仓库(此时本地分支并未关联远程分支)
git push -f origin feature/develop/today2
四、git生成patch和打patch
1、生成patch
git format-patch HEAD^ #生成最近的1次commit的patch git format-patch HEAD^^ #生成最近的2次commit的patch git format-patch HEAD^^^ #生成最近的3次commit的patch git format-patch HEAD^^^^ #生成最近的4次commit的patch git format-patch <r1>..<r2> #生成两个commit间的修改的patch(<r1>和<r2>都是具体的commit号, 左开右闭) git format-patch <r1>^..<r2> #生成两个commit间的修改的patch(包含<r1>和<r2>两个commit号) git format-patch -1 <r1> #生成单个commit的patch git format-patch -3 #从当前分支最新提交点往下共生成3个补丁 git format-patch <r1> #生成某commit以来的修改patch(不包含该commit) git format-patch --root <r1> #生成从根到r1提交的所有patch
2、打patch
命令:git am
和git apply
git apply是另外一种打patch的命令,其与git am的区别是,git apply并不会将commit message等打上去,打完patch后需要重新git add和git commit,而git am会直接将patch的所有信息打上去,而且不用重新git add和git commit,author也是patch的author而不是打patch的人
git apply --stat 0001-limit-log-function.patch # 查看patch的情况 git apply --check 0001-limit-log-function.patch # 检查patch是否能够打上,如果没有任何输出,则说明无冲突,可以打上 git am 0001-limit-log-function.patch # 将名字为0001-limit-log-function.patch的patch打上 git am --signoff 0001-limit-log-function.patch # 添加-s或者--signoff,还可以把自己的名字添加为signed off by信息,作用是注明打patch的人是谁,因为有时打patch的人并不是patch的作者 git am ~/patch-set/\*.patch # 将路径~/patch-set/\*.patch 按照先后顺序打上 git am --abort # 当git am失败时,用以将已经在am过程中打上的patch废弃掉(比如有三个patch,打到第三个patch时有冲突,那么这条命令会把打上的前两个patch丢弃掉,返回没有打patch的状态) $ git am --resolved #当git am失败,解决完冲突后,这条命令会接着打patch
如果打Patch的过程中发生了冲突(conflicts),怎么办?
解决patch冲突的过程是:
如果不想打这一系列patch了,直接:git am --abort。
如果还想打, 有两种解决方案:
方案一(个人推荐):
(1) 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply --reject <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch
(2) 根据.rej文件,通过编辑该patch文件的方式解决冲突。
(3) 废弃上一条am命令已经打了的patch:git am --abort
如果git am --abort 不起作用,可以使用rm -fr .git/rebase-apply代替
(4) 重新打patch:git am ~/patch-set/*.patchpatch
方案二:
(1) 根据git am失败的信息,找到发生冲突的具体patch文件,然后用命令git apply --reject <patch_name>,强行打这个patch,发生冲突的部分会保存为.rej文件(例如发生冲突的文件是a.txt,那么运行完这个命令后,发生conflict的部分会保存为a.txt.rej),未发生冲突的部分会成功打上patch
(2) 根据.rej文件,通过编辑发生冲突的code文件的方式解决冲突。
(3) 将该patch涉及到的所有文件(不仅仅是发生冲突的文件)通过命令git add <file_name>添加到工作区中
(4) 告诉git冲突已经解决,继续打patch: git am --resolved (git am --resolved 和 git am --continue是一样的)
分析:方案一和方案二主要区别是解决冲突的方法不一样。方案一是通过编辑patch文件的方式解决冲突,方案二十通过编辑冲突code文件的方式解决冲突。这两种方案区别比较大:经过实验,核心区别在于,方案二无法验证冲突有没有切实的解决。即使你在方案二的第二步乱改一通,也能“打完”发生冲突的patch(并没有检测修改后的code文件跟patch期望的是否相同)。因此,如果采用方案二,那么再解决code文件冲突后,需要人工去确认修改的正确性。
五、git cherry-pick的使用
作用:将某个分支的commit打到另一个分支上
# cherry-pick使用案例---打一个patch到某个分支 (1)切换到最终的分支上。如果需要将提交到分支yanghy/binder-new的commit(29259ee)合并到分支zhanghl/binder-new上面,则需要先切换到zhanghl/binder-new上面 (2)git cherry-pick 29259ee 如果有冲突,则解决冲突 git cherry-pick -x <commit id>:加上-x参数可以保留原提交者信息 (3)git add xxx (4)git commit xxxx (5)git cherry-pick --continue | git cherry-pick --quit | git cherry-pick --abort # cherry-pick使用案例---打多个patch到某个分支 git cherry-pick <start-commit-id>..<end-commit-id> 把<start-commit-id>到<end-commit-id>之间(左开右闭,不包含start-commit-id)的提交cherry-pick到当前分支; git cherry-pick <start-commit-id>^..<end-commit-id> 后者有^标志的表示把<start-commit-id>到<end-commit-id>之间(闭区间,包含start-commit-id)的提交cherry-pick到当前分支 注意:start-commit的时间要早于end-commit的时间
六、回退commit或者缓存
1、在工作区修改,但并未提交到暂存区(即并没有add)。
对于单个文件的撤销修改而言,使用下面方法。 git checkout -- 文件名
若想撤销工作区中所有文件的修改,则 git checkout .
注意:git chekcout 是让文件回到最近一次该文件git commit或git add时的状态。
2、工作区修改了之后,提交到了暂存区(即add),如何撤销修改?这里分为两种情况来说吧。
(1)对于该文件来说,在当前分支上,你还没有commit过一次。这时候,git status后git给出提示:
git reset HEAD
如果后面什么都不跟的话 就是上一次add 里面的全部撤销
git reset HEAD XXX/XXX/XXX.java
就是对某个文件进行撤销了
(2)对于要撤销的文件,你已经有了commit的记录了。
首先:git reset HEAD file
让该文件回到工作区的状态。
然后:git chekcout -- file
即可
git commit
:使用git commit -m “log信息” 如何添加多行log信息----使用单引号【’】添加多行log信息
使用git commit -s 进入门禁系统,进行log日志的书写,比git commit -m好用
git diff
:暂存区与当前工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有暂存起来的变化内容
就是git add文件(暂存区)的与再次修改的文件(工作目录)的区别
git diff --cached
:暂存起来的文件和上次提交时的快照之间的差异
就是git add之后的文件(暂存区)与git command的文件(版本库)的区别
git show
:当前commit与上一个commit之间的差异
git rm test.c
在暂存区中移除文件(从已跟踪清单中移除),并从工作区中删除该文件
git rm --cached test.c
把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然保留在当前工作目录中
git mv test.c test_change.c
重命名
相当于执行:
$ mv README.txt README $ git rm README.txt $ git add README
git log
查看提交历史
git log -p 查看提交(git commit)历史的同时,显示修改的具体信息 git log -2 只仅显示最近的两次更新 git log --graph --decorate --oneline --simplify-by-decoration --all 显示branch分支树结构 --decorate 标记会让git log显示每个commit的引用(如:分支、tag等) --oneline 一行显示 --simplify-by-decoration 只显示被branch或tag引用的commit --all 表示显示所有的branch,这里也可以选择,比如我指向显示分支ABC的关系,则将--all替换为branchA branchB branchC
git reset
git reset --hard 标签码 切换到某个提交的版本会保存暂存区和工作区的内容 彻底回退到某个版本,本地的源码也会变为上一个版本的内容,撤销的commit中所包含的更改被冲掉; git reset --soft 标签码 回退到某个版本,只回退了commit的信息,不会恢复到index file一级。如果还要提交,直接commit即可;
如果git reset发生错误了,则需要使用git reflog查看操作的版本
git reflog
查看提交记录
七、设置git
可以采用以下两种配置方式
1、修改git的相应配置都是修改在~/.gitconfig文件
2、使用命令行修改全局的属性
(1) 修改git的编辑器为vim编辑器
git config --global core.editor vim
(2)修改git的patch的提交作者和邮箱
git config --global user.name xxx
git config --global user.email xxx.com
(3)删除某一个属性
git config --global --unset user.name xxx
git config --global --unset-all user.name
3、查看git全局配置变量
git config --global --list
4、编辑git全局配置文件,会进去到交互窗口
git config -global --edit
配置某一个工程
1、修改某一个project下面的.git/config文件
2、使用命令行修改工程的属性
3、查看git 当前工程的皮配置属性
git config --local --list