[cs] git (2)
pull 与 fetch
pull=fetch+merge
,pull的话,下拉远程分支并与本地分支合并。
fetch
并没更改本地仓库的代码,只是拉取了远程 commit 数据,将远程仓库的 commit id 更新为latest。
rebase
git rebase用于把一个分支的修改合并到当前分支。
rebase一种情景:
假设你现在基于远程分支"origin",创建一个叫"mywork"的分支。
$ git checkout -b mywork origin
现在在这个分支做一些修改,然后生成两个提交(commit).
有些人也在"origin"分支上做了一些修改并且做了提交了.
这就意味着"origin"和"mywork"这两个分支各自"前进"了,它们之间"分叉"了。
在这里,可以用"pull"命令把"origin"分支上的修改拉下来并且和你的修改合并;
结果看起来就像一个新的"合并的提交"(merge commit).
如果想让"mywork"分支历史看起来像没有经过任何合并一样,可以用 git rebase:
$ git checkout mywork
$ git rebase origin
这些命令会把你的"mywork"分支里的每个提交(commit)取消掉,并且把它们临时 保存为补丁(patch)(这些补丁放到".git/rebase"目录中),然后把"mywork"分支更新 为最新的"origin"分支,最后把保存的这些补丁应用到"mywork"分支上。
当'mywork'分支更新之后,它会指向这些新创建的提交(commit),而那些老的提交会被丢弃。 如果运行垃圾收集命令(pruning garbage collection), 这些被丢弃的提交就会删除.
解决rebase冲突
在rebase的过程中,也许会出现冲突(conflict). 在这种情况,Git会停止rebase并会让你去解决 冲突;
在解决完冲突后,用git-add
命令去更新这些内容的索引(index), 然后,你无需执行 git-commit,只要执行:
$ git rebase --continue
这样git会继续应用(apply)余下的补丁。
$ git rebase --skip
跳过,注意此操作中当前分支的修改会直接覆盖目标分支的冲突部分。
在任何时候,你可以用--abort参数来终止rebase的行动,并且"mywork" 分支会回到rebase开始前的状态。
$ git rebase --abort
要注意谁是 ours 谁是 theirs
rebase 和 merge 的区别
git merge:
简单来说,它把两条不同分支历史的所有提交合并成一条线,并在“末端”打个结,即生成一次合并提交。最后形成一条单一的提交线。
git rebase:
根据参数的不同,行为有些差别。但总的来说,它相当于把分叉的两条历史提交线中的一条,每一次提交都捡选出来, 在另一条提交线上提交。最后也形成一条单一的提交线。
最终结果两者历史记录不同。
pull=fetch+merge
git pull --rebase #等于fetch + rebase
两种方式:
1.本地修改代码后,先stash,然后pull,pop,commit,push
2.本地修改代码后,commit(可多次),然后pull --rebase,push
第2种,本地的commit会在pull的内容的前面,
rebase尽量慎用,可能会导致同伴pull没rebase的版本然后提交冲突问题,自己的本地冲突问题也可能不那么好解决。
rebase交互模式
-i
或 --interactive
参数去调用交互模式。
操作对象是那些自最后一次从origin仓库拉取或者向origin推送之后的所有提交。
git rebase -i
#(action) (partial-sha) (short commit message)
stash
git stash 对当前的暂存区和工作区状态进行保存。
git stash list 列出所有保存的进度列表。
git stash pop [--index] [<stash>] 恢复工作进度
git stash apply [--index] [<stash>] 不删除已恢复的进度,其他同git stash pop
git stash drop [<stash>] 删除某一个进度,默认删除最新进度
git stash clear 删除所有进度
git stash branch <branchname> <stash> 基于进度创建分支
找回误删的stash
git stash pop
最后会打印出pop掉的commitid值,若这个记录还存在直接使用即可。
git fsck
, 会打印出所有的dangling commit, 悬挂的commit是不被任何branch引用的commit。 一般list出的第一个commit即是刚刚被pop掉的commit。
也可通过查看commit在commit graph中的位置确定对应的commitID.
git stash apply <commitID>
reset
回滚本地代码
git reset [ --soft | --mixed | --hard ]
--mixed
会保留源码,只是将git commit和index 信息回退到了某个版本.
git reset 默认是 --mixed
模式
如git reset HEAD^
--soft
保留源码,只回退到commit 信息到某个版本.不涉及index的回退,如果还需要提交,直接commit即可.
--hard
commit和index 都回回退到某个版本,本地代码也会回退到某个版本.
如git reset --hard origin/master
revert
回滚远程代码
git revert [commit id]
git revert用于反转提交,执行revert命令时要求工作树必须是干净的.
git revert用一个新提交来消除一个历史提交所做的任何修改.
revert 之后本地代码会回滚到指定的历史版本,这时再 git push 即可以把线上的代码更新.(不会像reset造成冲突的问题)
reset 是在正常的commit历史中,删除了指定的commit,这时 HEAD 是向后移动了,
而 revert 是在正常的commit历史中再commit一次,只不过是反向提交,他的 HEAD 是一直向前的.
alias shell脚本
git config --global alias.ac '!git add -A && git commit -m '
可以将 git add 和 git commit -m 这两条命令合二为一
接下来可以这样使用 git ac "提交信息"
#!/bin/bash
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.st status
git config --global alias.br branch
git config --global alias.mr merge
git config --global alias.rb rebase
git config --global alias.po "push origin"
git config --global alias.pl "pull origin"
git config --global alias.pu "pull upstream"
git config --global alias.alias "config --get-regexp ^alias\."
git config --global alias.unstage 'reset HEAD'
git config --global alias.last 'log -1'
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit" #这个超胖的
# This is for list all aliases
# Cache the credentials for 10 hours the next time you input them
git config --global alias.cache "config --global credential.helper 'cache --timeout=36000'"
echo "List all configured aliases"
git alias
conflict
<<<<<<< HEAD
本分支
=======
被合并分支
>>>>>>> dev
其他
git add -p
#可以一段一段地add,每一段都会问你要不要添加(y/n?)。
git blame [filename]
#会得到整个文件的每一行的详细修改信息:包括SHA串,日期和作者.
git diff master...
#如果用2个点进行diff,会把master的新增代码显示出来。
#用3个点进行diff,只会显示当前分支与master的最近公共祖先与当前分支的差异。
git push -u
#如果当前分支没有设置过track,这个命令会在push的同时,设置track。
git bisect start
#查找坏的branch
垃圾回收
Cleanup unnecessary files and optimize the local repository
git gc