rebase
多人在同一个分支上协作时,很容易出现冲突。即使没有冲突,后push的童鞋不得不先pull,在本地合并,然后才能push成功。那么怎么才能让提交历史变得干净,易读呢?可以使用rebase对某一段线性提交历史进行编辑、删除、复制、粘贴;因此,合理使用rebase命令可以使我们的提交历史干净、简洁!
$ git rebaseFirst,
rewinding head to replay your work on top of it...Applying:add commentUsingindex info to reconstruct a base tree...Mhello.pyFallingback to patching baseand3-way merge...Auto-merging hello.pyApplying:add authorUsingindex info to reconstruct a base tree...Mhello.pyFallingback to patching baseand3-way merge...Auto-merging hello.py
reset
git reset命令用于将当前HEAD复位到指定状态。一般用于撤消之前的一些操作(如:git add,git commit等)。
git reset [-q] [] [--] …
git reset (--patch | -p) [] [--] […]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] []
在第一和第二种形式中,将条目从<tree-ish>复制到索引。 在第三种形式中,将当前分支头(HEAD)设置为<commit>,可选择修改索引和工作树进行匹配。所有形式的<tree-ish>/<commit>默认为HEAD。
这里的HEAD关键字指的是当前分支最末梢最新的一个提交。也就是版本库中该分支上的最新版本。
在git的一般使用中,如果发现错误的将不想暂存的文件被git add进入索引之后,想回退取消,则可以使用命令:git reset HEAD <file>,同时git add完毕之后,git也会做相应的提示,
Submodule
当项目越来越庞大之后,不可避免的要拆分成多个子模块,我们希望各个子模块有独立的版本管理,并且由专门的人去维护,这时候我们就要用到git的submodule功能。
常用命令
git clone <repository> --recursive 递归的方式克隆整个项目
git submodule add <repository> <path> 添加子模块
git submodule init 初始化子模块
git submodule update 更新子模块
git submodule foreach git pull 拉取所有子模块
创建project版本库,并提交readme.txt文件
git init --bare project.git
git clone project.git project1
cd project1
echo "This is a project." > readme.txt
git add .
git commit -m "add readme.txt"
git push origin master
cd ..
创建moduleA版本库,并提交a.txt文件
git init --bare moduleA.git
git clone moduleA.git moduleA1
cd moduleA1
echo "This is a submodule." > a.txt
git add .
git commit -m "add a.txt"
git push origin master
cd ..
在project项目中引入子模块moduleA,并提交子模块信息
cd project1
git submodule add ../moduleA.git moduleA
git status
git diff
git add .
git commit -m "add submodule"
git push origin master
cd ..
2. 克隆带子模块的版本库
方法一,先clone父项目,再初始化submodule,最后更新submodule,初始化只需要做一次,之后每次只需要直接update就可以了,需要注意submodule默认是不在任何分支上的,它指向父项目存储的submodule commit id。
git clone project.git project2
cd project2
git submodule init
git submodule update
cd ..
方法二,采用递归参数--recursive,需要注意同样submodule默认是不在任何分支上的,它指向父项目存储的submodule commit id。
git clone project.git project3 --recursive
修改子模块
cd project1/moduleA
git branch
echo "This is a submodule." > b.txt
git add .
git commit -m "add b.txt"
git push origin master
cd ..
git status
git diff
git add .
git commit -m "update submodule add b.txt"
git push origin master
cd ..
更新子模块
方法一,先pull父项目,然后执行git submodule update,注意moduleA的分支始终不是master。
cd project2
git pull
git submodule update
cd ..
方法二,先进入子模块,然后切换到需要的分支,这里是master分支,然后对子模块pull,这种方法会改变子模块的分支。
cd project3/moduleA
git checkout master
cd ..
git submodule foreach git pull
cd ..
5. 删除子模块
网上有好多用的是下面这种方法
git rm --cached moduleA
rm -rf moduleA
rm .gitmodules
vim .git/config
删除submodule相关的内容,例如下面的内容
[submodule"moduleA"] url =/Users/nick/dev/nick-doc/testGitSubmodule/moduleA.git
然后提交到远程服务器
git add .
git commit -m "remove submodule"
.reflog
如果在回退以后又想再次回到之前的版本,git reflog 可以查看所有分支的所有操作记录(包括commit和reset的操作),包括已经被删除的commit记录,git log则不能察看已经删除了的commit记录
Administrator@USER-20171026MG MINGW64 ~/Desktop/lyf (master)
$ git reflog
e1bdff6 (HEAD -> master) HEAD@{0}: commit: 第二次提交
62e6739 HEAD@{1}: reset: moving to HEAD^
8113f0d HEAD@{2}: reset: moving to HEAD^
dc6bb4e HEAD@{3}: reset: moving to dc6bb4e
8113f0d HEAD@{4}: reset: moving to HEAD^
dc6bb4e HEAD@{5}: commit: my.txt增加44444内容
8113f0d HEAD@{6}: commit: 文件增加33333内容
62e6739 HEAD@{7}: commit (initial): my第一次提交
执行git blame;命令时,会逐行显示文件,并在每一行的行首显示commit号,提交者,最早的提交日期
给具体文件执行$git blame后的效果如下
6c2414fb (liangfei 2014-05-12 05:32:01 -0400 1) from markdown import markdown
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 2) from django.shortcuts import render
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 3) from django.core.paginator import Paginator, InvalidPage, EmptyPage
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 4) from blog.models import Post, Category
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 5)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 6)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 7) def category(request, cat_name, page_num=1):
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 8) if cat_name.lower() == 'home':
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 9) posts = Post.objects.all().order_by('-date')
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 10) else:
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 11) posts = Post.objects.all().filter(category__name=cat_name).order_by('-date')
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 12)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 13) paginator = Paginator(posts, 3)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 14) try:
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 15) page = int(page_num)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 16) except ValueError:
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 17) page = 1
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 18)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 19) try:
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 20) posts = paginator.page(page)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 21) except (InvalidPage, EmptyPage):
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 22) posts = paginator.page(paginator.num_pages)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 23)
6c2414fb (liangfei 2014-05-12 05:32:01 -0400 24) for post in posts:
6c2414fb (liangfei 2014-05-12 05:32:01 -0400 25) post.body = markdown(post.body)
6c2414fb (liangfei 2014-05-12 05:32:01 -0400 26)
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 27) return render(request, 'blog/index.html',
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 28) {
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 29) 'posts': posts,
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 30) 'cat_now': cat_name,
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 31) 'cat_all': map(lambda cat: cat.name, Category.objects.all())
be442bb4 (liangfei 2014-05-09 10:26:27 -0400 32) })
git stash 的作用
git stash用于想要保存当前的修改,但是想回到之前最后一次提交的干净的工作仓库时进行的操作.git stash将本地的修改保存起来,并且将当前代码切换到HEAD提交上.
通过git stash存储的修改列表,可以通过git stash list查看.git stash show用于校验,git stash apply用于重新存储.直接执行git stash等同于git stash save.
开发到一半,同步远端代码
当你的开发进行到一半,但是代码还不想进行提交 ,然后需要同步去关联远端代码时.如果你本地的代码和远端代码没有冲突时,可以直接通过git pull解决.但是如果可能发生冲突怎么办.直接git pull会拒绝覆盖当前的修改.
遇到这种情况,需要先保存本地的代码,进行git pull,然后再pop出本地代码:
git stash
git pull
git stash pop
工作流被打断,需要先做别的需求
当开发进行到一半,老板过来跟你说"线上有个bug,你现在给我改好,不然扣你鸡腿".当然,你可以开一个新的分支,把当前代码提交过去,回头再merge,具体代码如下
繁琐的工作流示例# ... hack hack hack ...git checkout -b my_wip git commit -a -m"WIP"git checkout master edit emergency fix git commit -a -m"Fix in a hurry"git checkout my_wip git reset --soft HEAD^# ... continue hacking ...
我们可以通过git stash来简化这个流程
正确姿势# ... hack hack hack ...git stash//保存开发到一半的代码edit emergency fix git commit -a -m"Fix in a hurry"git stash pop//将代码追加到最新的提交之后# ... continue hacking ...
提交特定文件
如果对多个文件做了修改,但是只想提交几个文件,或者想先暂时保存几个修改,测试其他文件的执行结果.可以通过git stash save --keep-index来进行.
# ... hack hack hack ...git add --patch foo//只将第一部分加入管理the indexgit stash save --keep-index//将其余部分保存起来edit/build/test first part git commit -m'First part'//提交全部的git管理中的代码git stash pop//继续进行存储代码的工作# ... repeat above five steps until one commit remains ...edit/build/test remaining parts git commit foo -m'Remaining parts'
恢复被错误clear/drop的存储
如果因为失误对存储仓库进行了clear或者drop操作,在一般机制下是不能恢复的.但是可以通过以下指令来获取仍在仓库中的,但是已经不可获取的存储列表
git fsck --unreachable |grep commit | cut -d\ -f3 |xargs gitlog--merges --no-walk --grep=WIP
git fetch
git fetch从远程分支拉取代码。
fetch常结合merge一起用,git fetch + git merge == git pull
一般要用git fetch+git merge,因为git pull会将代码直接合并,造成冲突等无法知道,fetch代码下来要git diff orgin/xx来看一下差异然后再合并。
作者:忆飞
链接:https://www.jianshu.com/p/a5c4d2f99807
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。