强制推送
书接上文,显示的提交者并非 johnmaster 而是一个名为 os_lab_user 的用户,这是因为Github是通过提交中的邮件地址来对应到Github用户的。
$ git log --pretty=fuller
![2be8b0daec7bd80bff761f2ae9b7fc2c.png](https://i-blog.csdnimg.cn/blog_migrate/54143fde4310f8a0f30b58865b9f59c8.jpeg)
原来提交用户设置的邮件地址并非johnmaster用户设置的邮件地址。
补救的方法就是对此提交进行修改,然后强制推送到Github。
- 重新设置 user.name 和 user.email 配置变量
下面的设置命令中没有使用 --global 参数,只对本地 helloworld 版本进行设置。
$ git config user.name "johnmaster"
$ git config user.email "544954556.com"
- 执行Git修补提交命令
注意使用参数 --reset-author 会将提交信息中的属性 author 连同 AuthorDate 一并修改,否则只修改 Commit 和 CommitDate。参数 -C HEAD 维持提交说明不变。
$ git commit --amend --reset-author -C HEAD
- 查看提交日志,发现提交者信息和作者信息都已经更改。
![8c59526a75d3d15023f890862820c471.png](https://i-blog.csdnimg.cn/blog_migrate/d604f24f84e52aa4ae0f138d3e2becc7.jpeg)
- 直接推送会报错
$ git push
![bc6663a31683d602750b4986e2f9fc3a.png](https://i-blog.csdnimg.cn/blog_migrate/37cb22d7a8dd9e53b97db2e49933947f.jpeg)
错误信息中出现 non-fast-forward(非快进式推送),含义为要推送的提交并非继远程版本库最新提交之后的提交,推送会造成覆盖导致服务器端有数据(提交)会丢失。
- 使用强制推送
考虑到没有其他人关注helloworld这个刚建立起来的项目,显然不需要向上面命令的错误信息所提示的那样先执行 git pull 合并上游版本库再推送,而是选择强制推送,以新的修补提交覆盖包含错误提交者ID的提交。
$ git push -f
![d844fa4f76da2fac86b49bb69690dac6.png](https://i-blog.csdnimg.cn/blog_migrate/1b43355b447745da63bfa971004e59ec.jpeg)
完成强制推送后,再查看Github项目页面,提交者已经显示为johnmaster用户。
Git分支
当我们创建一个仓库并对仓库进行初始化之后,该仓库就会创建一个默认的 master 分支,而这个 master 分支可以被当作是最开始的主分支。
Git分支的创建不限制于网络,具有本地特性,而且还可以根据我们的需求来创建多个分支,这些分支可以是为了修复程序中的某个bug而存在,或者是为了增加当前程序的一些新特性而使用的。
分支的创建能够很好的让我们的操作与开发主线进行隔离,特别是以分布式方式进行的开源项目会设计到众多的人员,为了不让我们的修改影响到主线程序,只有通过审核后的代码才能够合并到主线中去,所以通过使用分支是最理想的方法。
新建分支
Git的分支就是保存在 .git/refs/heads/命名空间下的引用。引用文件的内容是该分支对应的提交ID。当前版本库中的默认分支 master 就对应于文件 .git/refs/heads/master。
若在Github版本库中创建分支,首先要在本地版本库中创建新的分支(即引用),然后用推送命令将本地创建的新的引用连同所指向的提交推送到Github版本库中完成Github上分支的创建。操作如下
- 本地版本库中建立新分支 mybranch1
$ git checkout -b mybranch1
创建分支有许多种方法,例如使用 git branch 命令,但最为便捷的就是 git checkout -b 命令。
![a4be8c60d1e7f2bc66a04dcc009bccb8.png](https://i-blog.csdnimg.cn/blog_migrate/bc49a56de4c43d985b0b740e246d2be5.png)
- 为了易于识别,添加一个新文件 hello1,并提交
$ touch hello1
$ git add hello1
$ git commit -m "add hello1 for mark"
- 通过推送命令,将本地分支 mybranch1 推送到Github远程版本库,完成Github上的新分支创建。
$ git push -u origin mybranch1
在Github上查看版本库,会看到新增了一个分支 mybranch1,不过默认分支仍为 master,如图所示,
![c9c307a68633f372078bf8bcd38feb25.png](https://i-blog.csdnimg.cn/blog_migrate/93bd117126b41a10f4502db4b5d44886.png)
设置默认分支
可以改变Github上版本库显示的默认分支,如果版本库包含多个分支的话。例如修改版本库的默认分支为 mybranch1,
![5f30e6d5ff6521cda6c4f03edc5804f0.png](https://i-blog.csdnimg.cn/blog_migrate/b10cfd1dc6565234e895271d305145e9.jpeg)
设置了Github默认分支后,如果再从Github克隆版本库,本地克隆后版本库的默认分支也将改变。
$ git clone https://github.com/johnmaster/helloworld helloworld-nb
$ cd helloworld-nb
$ git branch
![74f819b43dd65c012ebacf989285e92b.png](https://i-blog.csdnimg.cn/blog_migrate/e973c746be7192abafd876064163999b.png)
实际上修改Github上版本库的默认分支,就是将Github版本库的头指针HEAD指向了其他分支,如 mybranch1 分支
$ git branch -r
![7eca8af85084da6f1ad5ba5d076f4437.png](https://i-blog.csdnimg.cn/blog_migrate/89a7c1cd0ac83f4433028215e550cd8f.png)
删除分支
删除当前分支会报错
$ git branch -d mybranch1
![a78444c1d02ccf50caa3f0b151ad5b8c.png](https://i-blog.csdnimg.cn/blog_migrate/ae778aa0deb822cac2fd49b5d85eafcf.png)
错误信息显示不能删除当前工作分支,因此先切换到其他分支
$ git checkout master
可以看出新的工作分支为 master 分支
$ git branch
![582429ddb823011f9a2baf6649a201c7.png](https://i-blog.csdnimg.cn/blog_migrate/6df89a1507dd861318b6b8ea8188aeb9.png)
现在可以删除mybanch1分支,下面的命令使用 -D 参数,而非 -d参数,是因为Git在删除分支时为避免数据丢失,默认禁止删除尚未合并的分支。参数 -D 则可强制删除尚未合并的分支
$ git branch -D mybranch1
![d0d31c79442109d677fb145556df3aac.png](https://i-blog.csdnimg.cn/blog_migrate/0d7b20dbdf3022d5565e096e6c225af3.png)
现在只是本地分支被删除了,远程Github服务器上的 mybranch1分支尚在。删除远程Github版本库中的分支就不能使用 git branch命令,而是要使用 git push 命令,不过在使用推送分支命令时要使用一个特殊的引用表达式(冒号前为空),如下:
$ git push origin :mybranch1
![42253a90d4f4189d32bd99cacd9bab2e.png](https://i-blog.csdnimg.cn/blog_migrate/ec5d1af58075e4858016a373f7f1521f.png)
删除远程分支出错,实际上使用强制推送也会遇到上面的错误,Github发现要删除的 mybranch1分支时远程版本库的默认分支,因而禁止删除,重新访问Github的项目管理页面,将默认分支设置回 master 分支,然后再次执行上面的命令,即可成功删除分支。
里程碑
里程碑就是平常我们看到的软件标识与版本号,每一个版本号都代表了开发人员工作的完结,以及下一段工作的开始。
当软件发布以后,我们就需要建立一个里程碑,方便我们将来能够将一个完整的软件发布出去,也方便将来能够快速寻找某个版本的代码去修复一些问题。
![81bb9e590f8c6e70de10640fad4ec9a6.png](https://i-blog.csdnimg.cn/blog_migrate/1a2538457eda45a8de6f58642d444045.png)
里程碑管理
里程碑即tag。里程碑和分支一样也是以引用的形式存在的,保存在 .git/refs/tags/ 路径下。
- 轻量级里程碑
用 git tag <tagname> [<commit>] 命令创建,引用直接指向一个提交对象 <commit>。
- 带说明的里程碑
用 git tag -a <tagname> [<commit>]命令创建,并且在创建时需要提供创建里程碑的说明。Git 会创建一个tag对象保存里程碑说明,里程碑的指向,创建里程碑的用户等信息,里程碑引用指向该 Tag 对象。
- 带签名的里程碑
用 git tag -s <tagname> [<commit>]命令创建。是在带说明的里程碑的基础上引入了PGP签名,保证了所创建的里程碑的完整性和不可拒绝性。
下面演示一下里程碑的创建和管理。
- 先在本地创建一个新提交
$ touch hello1
$ git add hello1
$ git commit -m "add hello1 for mark."
- 本地创建里程碑 mytag1,mytag2和mytag3
$ git tag -m "Tag on initial commit" mytag1 HEAD^
$ git tag -m "Tag on new commit" mytag2
$ git tag mytag3
- 查看新建立的里程碑
$ git tag -l -n1
- 将本地里程碑推送到Github远程版本库
$ git push origin refs/tags/*
- 删除本地里程碑
$ git tag -d mytag3
- 删除Github远程版本库中的里程碑
$ git push origin :mytag3