246 lines
7.8 KiB
JavaScript
246 lines
7.8 KiB
JavaScript
|
||
|
||
|
||
|
||
## 常见操作
|
||
|
||
### 全局配置用户信息
|
||
|
||
```
|
||
git config --global user.name "smyhvae"
|
||
|
||
git config --global user.email "smyhvae@163.com"
|
||
```
|
||
|
||
|
||
## 分支的合并
|
||
|
||
|
||
### 场景:基于master分支的代码,开发一个新的特性
|
||
|
||
如果你直接在master分支上开发这个新特性,是不好的,万一你在开发`特性1`的时候,领导突然又要叫你去开发`特性2`,就不好处理了。难道开发的两个特性都提交到master?一会儿提交特性1的commit,一会儿提交特性2的commit?这会导致commit记录很混乱。
|
||
|
||
所以,我给你的建议做法是:给每个特性都单独建一个的新的分支。
|
||
|
||
比如说,我专门给`特性1`建一个分支`feature_item_recommend`。具体做法如下:
|
||
|
||
(1)基于master分支,创建一个新的分支,起名为`feature_item_recommend`:
|
||
|
||
```
|
||
$ git checkout -b feature_item_recommend
|
||
|
||
Switched to a new branch 'feature_item_recommend'
|
||
```
|
||
|
||
上面这行命令,相当于:
|
||
|
||
|
||
```bash
|
||
$ git branch feature_item_recommend // 创建新的分支
|
||
|
||
$ git checkout feature_item_recommend //切换到新的分支
|
||
```
|
||
|
||
|
||
(2)在新的分支`feature_item_recommend`上,完成开发工作,并 commit 、push。
|
||
|
||
(3)将分支`feature_item_recommend`上的开发进度**合并**到master分支:
|
||
|
||
```bash
|
||
$ git checkout master //切换到master分支
|
||
|
||
$ git merge feature_item_recommend //将分支 feature_item_recommend 的开发进度合并到 master 分支
|
||
|
||
```
|
||
|
||
|
||
合并之后,`master`分支和`feature_item_recommend`分支会指向同一个位置。
|
||
|
||
|
||
(3)删除分支`feature_item_recommend`:
|
||
|
||
> 既然 特性1 开发完了,也放心地提交到master了,那我们就可以将这个分支删除了。
|
||
|
||
```
|
||
git branch -d feature_item_recommend
|
||
```
|
||
|
||
注意,我们当前是处于`master`分支的位置,来删除`feature_item_recommend`分支。如果当前是处于`feature_item_recommend`分支,是没办法删除它自己的。
|
||
|
||
同理,当我转身去开发`特性2`的时候,也是采用同样的步骤。
|
||
|
||
|
||
### 合并分支时,如果存在分叉
|
||
|
||
|
||
![](http://img.smyhvae.com/20180610_1650.png)
|
||
|
||
|
||
比如说上面这张图中,最早的时候,master分支是位于`C2`节点。我基于`C2`节点,new出一个新的分支`iss53`,我在`iss53`上提交了好几个commit。
|
||
|
||
现在,我准备把`iss53`上的几个commit合并到master上,此时发现,master分支已经前进到C4了。那该怎么合并呢?
|
||
|
||
合并的命令仍然是:
|
||
|
||
```bash
|
||
$ git checkout master
|
||
|
||
$ git merge iss53
|
||
```
|
||
|
||
**解释**:
|
||
|
||
这次合并的实现,并不同于简单的并入方式。这一次,我的开发历史是从更早的地方开始分叉的。
|
||
|
||
由于当前 master 分支所指向的commit (C4)并非想要并入分支(iss53)的直接祖先,Git 不得不进行一些处理。就此例而言,Git 会用两个分支的末端(C4 和C5)和它们的共同祖先(C2)进行一次简单的三方合并计算。
|
||
|
||
Git 没有简单地把分支指针右移,而是对三方合并的结果作一新的快照,并自动创建一个指向它的commit(C6)(如下图所示)。我们把这个特殊的commit 称作合并提交(mergecommit),因为它的祖先不止一个。
|
||
|
||
值得一提的是Git 可以自己裁决哪个共同祖先才是最佳合并基础;这和CVS 或Subversion(1.5 以后的版本)不同,它们需要开发者手工指定合并基础。所以此特性让Git 的合并操作比其他系统都要简单不少。
|
||
|
||
![](http://img.smyhvae.com/20180610_1710.png)
|
||
|
||
### 解决合并时发生的冲突
|
||
|
||
![](http://img.smyhvae.com/20180610_1740.png)
|
||
|
||
如果 feature1和feature2修改的是同一个文件中**代码的同一个位置**,那么,把feature1合并到feature2时,就会产生冲突。这个冲突需要人工解决。步骤如下:
|
||
|
||
(1)手动修改文件:手动修改冲突的那个文件,决定到底要用哪个分支的代码。
|
||
|
||
(2)git add:解决好冲突后,输入`git status`,会提示`Unmerged paths`。这个时候,输入`git add`即可,表示:**修改冲突成功,加入暂存区**。
|
||
|
||
(3)git commit 提交。
|
||
|
||
然后,我们可以继续把 feature1 分支合并到 master分支,最后删除feature1、feature2。
|
||
|
||
**注意**:两个分支的同一个文件的不同地方合并时,git会自动合并,不会产生冲突。
|
||
|
||
比如分支feture1对index.html原来的第二行之前加入了一段代码。
|
||
分支feature2对index.html在原来的最后一行的后面加入了一段代码。
|
||
这个时候在对两个分支合并,git不会产生冲突,因为两个分支是修改同一文件的不同位置。
|
||
git自动合并成功。不管是git自动合并成功,还是在人工解决冲突下合并成功,提交之前,都要对代码进行测试。
|
||
|
||
## 日常操作积累
|
||
|
||
### 修改密码(曲线救国)
|
||
|
||
|
||
> 网上查了很久,没找到答案。最终,在cld童鞋的提示下,采取如下方式进行曲线救国。
|
||
|
||
```bash
|
||
# 设置当前仓库的用户名为空
|
||
git config user.name ""
|
||
```
|
||
|
||
然后,当我们再输入`git pull`等命令行时,就会被要求重新输入*新的*账号密码。此时,密码就可以修改成功了。最后,我们还要输入如下命令,还原当前仓库的用户名:
|
||
|
||
```
|
||
git config user.name "smyhvae"
|
||
```
|
||
|
||
### 修改已经push的某次commit的作者信息
|
||
|
||
已经push的记录,如果要修改作者信息的话,只能 通过--force命令。我反正是查了很久,但最终还是不敢用公司的仓库尝试。
|
||
|
||
参考链接:
|
||
|
||
|
||
- [git 修改已提交的某一次的邮箱和用户信息](https://segmentfault.com/q/1010000006999861)
|
||
|
||
看最后一条答案。
|
||
|
||
- [修改 git repo 历史提交的 author](http://baurine.github.io/2015/08/22/git_update_author.html)
|
||
|
||
|
||
### 将 `branch1`的某个`commit1`合并到`branch2`当中
|
||
|
||
切换到branch2中,然后执行如下命令:
|
||
|
||
```
|
||
git cherry-pick commit1
|
||
```
|
||
|
||
### 20190118-修改GitHub已提交的用户名和邮箱
|
||
|
||
参考链接:(亲测有效)
|
||
|
||
- [修改Git全部Commit提交记录的用户名Name和邮箱Email](https://cloud.tencent.com/developer/article/1352623)
|
||
|
||
- [Mac 运行sh文件,也就是传说中的shell脚本](https://blog.csdn.net/yusufolu9/article/details/53706269)
|
||
|
||
|
||
在执行`./email.sh`后,如果出现`permission denied`的错误,可以先执行`chmod 777 email.sh`,修改文件的权限。
|
||
|
||
|
||
### 20200520-将Git 项目迁移到另一个仓库
|
||
|
||
我们假设旧仓库的项目名称叫`old-repository`,新仓库的项目名称叫`new-repository`。操作如下:
|
||
|
||
|
||
(1)创建旧仓库的裸克隆:
|
||
|
||
```bash
|
||
git clone --bare https://github.com/exampleuser/old-repository.git
|
||
```
|
||
执行上述命令后,会在本地生成一个名叫 `old-repository.git`的文件夹。
|
||
|
||
|
||
(2)迁移到新仓库:
|
||
|
||
```bash
|
||
cd old-repository.git
|
||
|
||
git push --mirror https://github.com/exampleuser/new-repository.git
|
||
```
|
||
|
||
这样的话,项目就已经迁移到新仓库了。
|
||
|
||
注意,我们**不需要**手动新建一个空的新仓库,当我们执行上述命令之后,新仓库就已经自动创建好了。
|
||
|
||
参考链接:
|
||
|
||
- [复制仓库](https://help.github.com/cn/github/creating-cloning-and-archiving-repositories/duplicating-a-repository)
|
||
|
||
- [Git 本地仓库和裸仓库](https://moelove.info/2016/12/04/Git-%E6%9C%AC%E5%9C%B0%E4%BB%93%E5%BA%93%E5%92%8C%E8%A3%B8%E4%BB%93%E5%BA%93/)
|
||
|
||
|
||
|
||
|
||
## git客户端推荐
|
||
|
||
市面上的Git客户端我基本都用过了,我最推荐的一款Git客户端是:[Tower](https://www.git-tower.com) 或者 [Fork](https://git-fork.com)。
|
||
|
||
- GitUp:<https://gitup.co/>
|
||
|
||
20180623时,网上看了下Git客户端的推荐排名:
|
||
|
||
![](http://img.smyhvae.com/20180623_1210.png)
|
||
|
||
**SmartGit**:
|
||
|
||
商业用途收费, 个人用户免费:
|
||
|
||
![](http://img.smyhvae.com/20180623_1305.png)
|
||
|
||
|
||
|
||
|
||
|
||
## 推荐书籍
|
||
|
||
- 《pro.git中文版》
|
||
|
||
|
||
|
||
## 推荐连接
|
||
|
||
|
||
### 2018-06
|
||
|
||
- [聊下git pull --rebase](https://www.cnblogs.com/wangiqngpei557/p/6056624.html)
|
||
|
||
|
||
|
||
|