Git学习总结2

以下Git学习内容,来自官方文档,本文整理学习过程笔记。

Git鼓励在工作流程中频繁地使用分支与合并。Git创建分支,只创建了一个可以移动的新指针(指向包含所指对象校验和的文件),HEAD指针始终指向当前的工作分支。修改当前分支,也仅仅是更改HEAD指针的值,使其指向新分支。

Git分支操作

  1. 查看当前分支:git branch,当前分支前有*
  2. 删除本地hotfix分支, git branch -d hotfix
  3. 删除远程serverfix分支: git push origin --delete serverfix
  4. 查看哪些分支已经合并到当前分支:git branch --merged
  5. 查看未合并到当前分支的分支: git branch --no-merged
  6. 切换到master分支: git checkout master
  7. 合并pro分支到master分支:git checkout mastergit merge pro
    • 默认使用Fast Forward模式合并,不会产生新的commitId。为保证合并数据的完整性,可通过 --no-ff 选项,禁用Fast Forward模式合并,禁用后合并会生成新的commitId
  8. 将本地serverfix分支推送到远程origin仓库中,更新远程仓库的serverfix分支(如果没有会新建该分支): git push origin serverfix

分支冲突解决

查看有哪些冲突文件:

git status,查看处于 unmerged paths 状态的文件。Git会在有冲突的文件中加入标准的冲突解决标记,需要手动打开这些文件来解决冲突。冲突标记实例如下:


	<<<<<<< HEAD:index.html
	<div id="footer">contact : email.support@github.com</div>
	=======
	<div id="footer">
 	please contact us at support@github.com
	</div>
	>>>>>>> iss53:index.html

HEAD为当前分支的版本,=====区段的上半部分至HEAD的内容是当前分支中有冲突的内容,区段的下半部分到iss53,是iss53分支中有冲突的内容。为了解决该冲突,必须手动选择使用哪一部分。

在解决完所有文件的冲突后,对每个文件使用git add来将其标记为冲突已解决。最后,输入 git commit 来完成合并后的提交。

线上Bug处理流程 ###

在基于master分支进行开发,如遇到线上版本的Bug,需切换到线上版本分支时,可通过暂存或者修复本地提交的方法保存当前修改内容,然后切换回master分支,新建hotfix分支来处理线上问题。处理完毕后,合并hostfix分支内容到master分支,然后删除hotfix分支。

分支切换注意事项

在切换分支时,一定要注意你工作目录的文件会被改变。如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。如果Git不能干净利落地完成这个认为,它将禁止切换分支,一般会有如下提示:

`Your local changes to the following files would be overwritten by merge`.

针对此问题,有以下两种解决方法:
方法1:保留本地提交修改

1. 暂存当前任务,再进行操作。
	* git stash // 暂存当前工作
	* xxxx
	* git stash pop // 恢复之前工作
2. 将修改提交到本地仓库
	* git add .
	* git commit -m "message"

方法2:舍弃本地修改

1.  清除未跟踪文件
	* git clean -n // 清除文件预览,先确认
	* git clean -f // 强制清除文件

变基操作

提取另一分支的修改,在master分支上应用一次,这种操作叫做变基(rebase)。该命令可将提交到某一分支上的所有修改都移动到另一分支上,就好像重新播放一样。操作流程如下:

  • 切换到开发分支:git checkout experiment
  • 将该分支的改动移动到master分支: git rebase master
  • 切换到mater分支:git checkout master
  • 进行快速合并:git merge experiment

查看经过变基操作的提交会发现,尽管是并行开发,但是提交历史是一条直线,没有分叉。

适用场景:为了确保在向远程分支推送时,保持提交历史的整洁。
例如:向其他人项目贡献代码时,你先在自己的分支里进行开发,当开发完成时,你需要下将你的代码变基到 origin/master上,然后再向主项目提交修改,这样的话,该项目的维护者就不需要进行整合工作,只需要快进合并即可。

风险:如果提交存在于你的仓库之外代码,而别人可能基于这些提交进行开发,那么不要执行变基。

远程仓库

git clone:默认克隆远程仓库中每个文件的所有历史信息,自动设置本地master分支跟踪远程仓库的master分支,添加远程仓库(缩写为origin)关联。

查看本地已配置的远程仓库服务器: git remote -v,显示本地关联的远程仓库地址以及简写。

$ git remote -v
origin	https://github.com/schacon/ticgit (fetch)
origin	https://github.com/schacon/ticgit (push)

查看远程仓库的详细信息: git remote show <remote>

git fetch只会将数据下载到你本地仓库,不会自动合并或修改你当前的工作。

如果你的当前分支设置了跟踪远程分支,那么可以用git pull来抓取并合并远程分支修改到当前分支,即git pull = git fecth + git merge

推送本地修改到远程仓库

当你想分享你的项目时,必须将其推送到远程仓库,可使用 git push <remote> <branch>语法。

git push origin master,推送本地master分支到origin仓库的master分支。

开源项目协作

以项目贡献者视角:

  1. 克隆远程主仓库:git clone <url>
  2. 新建特性分支,并在此分支上工作: git checkout -b featureA
  3. 当此分支上的工作完成后,去原始项目中点击Fork按钮,创建一份自己仓库的派生项目。
  4. 将本地仓库关联上3)中的远端仓库: git remote add myFork <url>。其中,myFork是远端仓库的简写,url为自己fork下来的远端仓库地址
  5. 推送本地分支的修改到远端仓库。 git push -u myFork featureA
  6. 向原项目的维护者发出拉取请求(Pull Request

如果远端分支已经有更新,为了减少维护者合并过程中的冲突,可将源版本库添加一个新的远端,并从远端抓取内容,合并主分支的内容到开发分支中,修复所有问题并最终重新推送回你提交拉取请求使用的分支。

  • 添加远程上游仓库: git remote add upstream <url>
  • 获取远程上游仓库的master分支内容:git fetch upstream
  • 合并远程master分支内容到本地master分支:
    • git checkout master
    • git merge upstream/master
  • 修复产生的冲突
  • 再推送回同一个分支。git push origin master

以项目维护者视角:

  1. 在本地仓库添加贡献者(Jessica)的远程分支,git remote add Jessica git://github.com/jessica/myproject.git
  2. 拉取远程实现。 git fetch jessica
  3. 在本地新建分支,并拉取对应分支功能:
    • git checkout -b rubyclient jessica/ruby-client。将远程仓库下的ruby-client分支内容提取到本地 rubyclient 分支。
  4. 查看贡献分支与本地分支的差异。 git diff master...rubyclient

其他项目贡献者视角:

  1. 使用git fetch origin,拉取远程修改
  2. 同步远程修改
    • 方法一: 将上游工作合并到当前所在分支:git merge origin/serverfix
    • 方法二:本地新建分支并跟踪远程分支:git checkout -b servierfix origin/serverfix
      • 该操作很常用,因此,Git提供 git checkout --track origin/serverfix来简化,更近一步,如果本地无同名分支,且想创建一个与远程分支名字相同的分支,直接 git checkout serverfix 即可完成。

让GitHub公共仓库保持更新

  1. 切换到master分支: git checkout master
  2. 拉起最新项目分支内容: git pull https://github.com/progit/progit2.git
  3. 将本地最新master分支内容推送到远端的fork仓库: git push origin master

上面是从指定远端仓库抓取内容到本地,然后推送修改到GitHub远程仓库。可通过如下设置来简化流程:

  1. 添加远程仓库并起一个别名progitgit remote add progit https://github.com/progit/progit2.git
  2. 设置本地master分支对应的上游仓库信息: git branch --set-upstream-to=progit/master master
  3. 将默认推送操作的远程仓库信息:git config --local remote.pushDefault origin

经过上述设置,以后可这样更新:

  1. git checkout master
  2. git pull: 从源项目仓库拉取更新
  3. git push:将此更新推送到远程fork项目中。

Git搜索工具

git grep -n key_word:输出Git找到的匹配key_word的行号

想知道某个标示符是什么时候存在的或引入的。

  • git log -S ZLIB_BUF_MAX --oneline: 显示新增和删除ZLIB_BUF_MAX的提交记录

行日志搜索,展示代码中一行或者一个函数的提交历史。例如:查看zlib.c文件中 git_deflate_bound 函数的每一次变更,执行:

  • git log -L :git_deflate_bound:zlib.c

Git内部原理

Git是一个内容寻址文件系统,核心是一个可存储任意数据的键值对数据库。键由数据内容加上特定头部信息计算SHA-1的来的。

.git隐藏目录中,有以下重要的文件和目录:

  • HEAD文件:指向目前被检出的分支
  • index文件:保存暂存区信息
  • objects目录:存储所有数据内容,数据内容校验和的前两个字符用于命名子目录,余下的字符用作文件名。
  • refs目录:存储指向数据的提交对象的指针

Git中的数据在内部以数据对象(blob object)存在,目录以树对象(tree object)形式存在。

Git在每一次提交时,会生成提交对象(commit object),该对象记录提交的快照信息以及父提交对象,这样,可通过最新提交对象往前回溯,寻找提交历史。

上层运行git addgit commit时,Git实际做以下操作:

  1. 将被改写的文件保存为数据对象,更新暂存区
  2. 记录树对象
  3. 创建一个提交对象(包含顶层树对象和本次提交的父提交对象)。

Git中数据内容的头部结构为:数据格式、空格、是数据内容字节数和一个空字节,以下为一个简单的例子:

"blob 16\u0000"

Git中有三种主要的数据格式:

  1. blob: 数据内容对象
  2. tree: 树对象
  3. commit:提交对象

git gc命令会收集所有松散对象,并将它们放置到包文件中,将多个包文件合并为一个大的包文件,移除与任何提交都不相关的陈旧对象。

posted @ 2021-08-18 14:20  浩天之家  阅读(89)  评论(0编辑  收藏  举报