likes
comments
collection
share

工具- git 低频命令

作者站长头像
站长
· 阅读数 3

前言

虽然现在git都用可视化了,但是我还是比较喜欢结合命令行去做一些事情,尤其是在批量操作的仓库的时候。 恰好最近接触到了一个大型项目,需要频繁的同步各个版本的仓库,并在这上面浪费了很多的时间,有一些场景还是值得记录一下的。

正常流程

# 最基本
1- 新建仓库/分支
2- git clone 
3- git add .
4- git commit -m 'aaa'
5- git push

# 本地开始
1- git init
2- git remote add origin "http://gitee..."
3- git push 

# 开发特性功能
1- git clone
2- git checkout -b feature/造火箭
3- git add .
4- git commit -m '做推进器1'
5- git add .
6- git commit -m '做推进器2'
7- git add .
8- git commit -m '做推进器3'
9- git checkout master
10- git pull
11- git merge feature/造火箭
12- git push

小细节(多远程仓库)

  1. git push "远程地址别名" "分支名(可加可不加)"
  2. git pull "远程地址别名" "分支名(可加可不加)"
  3. git remote add "远程地址别名" "仓库地址"
  4. git merge --strategy-option=ours/theirs B
  5. git add fileA fileB
  6. git checkout -- [fileA fileB]/ .

几个稍微特殊的场景

场景一

前置条件:仓库 A(有上千个 commit 记录),空仓库 B。 需求:基于仓库 A branch v1.0 commitID asd12345 创建新的分支 v1.0-feature 提交到 仓库 B,并保留 commit 记录。

场景二

前置条件:仓库 A(很复杂),仓库 B是由 仓库A 通过场景一分离出去的,已经有了新的 commit tree。 需求:将仓库 A 中的 连续/不连续 的commit 合并进 仓库 B 的 v1.0-feature 分支,不打乱原有的 commit 记录。

场景三

前置条件:仓库 A(很复杂),主分支 master、特性分支 feature1、开发分支 dev1,feature1 早于 dev1 且有冲突。 需求:完整的提取 feature ,并 不影响现在的dev环境。

场景四

正常开发 add commit push,因为 commit 不够美观,最新一个 commit 不想要了。

场景五

一个 demo 库性质的仓库,即你下载了别人的一个仓库,仓库的提交记录特别整齐,每个 commit 都是一个完整的 demo,你想要把 某个 demo 放在你的项目里面,即 cherrypick 一个跟你的仓库完全没关系的 commitID。

场景六

一个仓库两个团队都在更新内容,如何确保代码合并时候,双方都不会受到影响?

场景七

三个分支,一个是持续迭代分支,一个是主分支,还有一个或多个是新需求分支,合并需求的时候,发现需求分支上旧版本把另一个迭代版本覆盖了。

场景八

一个需求经过开发、联调、上线、解决bug一系列操作才完成,希望能把这一系列的 commitID 合并成 一条记录。

场景九

配置一个本地仓库,可以向客户A、客户B、公司仓库推送代码。

一个综合性比较强的场景

echo -e "\033[36m :: Start 克隆远程仓库 -fe-watermark-- \033[0m" && 
git clone https://gitee.com/RELEASE/watermark.git && 
echo -e "\033[36m :: 进入仓库 fe-watermark --- \033[0m" && 
cd fe-watermark &&  
echo -e "\033[36m :: 添加新远程地址 \033[0m" &&  
git remote add kt https://github.com/project/watermark.git &&
git remote -v &&
echo -e "\033[36m :: 切换至目标分支 --- \033[0m" && 
git checkout di/dev-v1.2.0 &&
echo -e "\033[36m :: 推送 dev_1.0.0--- \033[0m" && 
git checkout -b dev_1.0.0 && git push kt dev_1.0.0 -f &&
echo -e "\033[36m :: 拉取 master--- \033[0m" && 
git pull kt master && git checkout master && 
echo -e "\033[36m :: 比对 master | di/dev-v1.2.0--- \033[0m" && 
git diff di/dev-v1.2.0 master && 
echo -e "\033[36m :: 重置 master--- \033[0m" && 
git reset --hard dev_1.0.0 && 
echo -e "\033[36m :: 再次比对 master | di/dev-v1.2.0--- \033[0m" && 
git diff di/dev-v1.2.0 master && 
echo -e "\033[36m :: 推送 master--- \033[0m" && 
git push kt master -f &&
echo -e "\033[36m :: 完成 - Exit --  \033[0m" && 
cd ..

具体场景是这样的,有一个大型项目,仓库30+,需要对所有的仓库都新建一个仓库并且将现有仓库的指定分支重命名推送到新的仓库,并且master要和这个重命名的分支同步。

举个现实场景就是,我们公司开发的代码,基于 dev-1.2 改成 xxx-1.0 并新建仓库交付给客户,然后加个小条件就是把现在的代码放在master分支上。很不巧的是,昨天刚做了一趟,现在而且代码管理员很贴心的给了另一套仓库地址,里面的分支更加清晰。

就是说,我昨天从 A 列表中 将 a 分支 改名 为 a1 同步到了 B 列表,现在 又要把 C 列表当做 A 列表再来一次。关键点是不同源了。B列表又不能新建一遍。

好像工作并不难,难的是如何保证不出错,高效的完成这件事情,即便出错了也能很快的追溯当时发生了什么,迅速的进行解决。

如上命令调用所示,直接实现了这个情况。核心有两个:

  • push -f
  • reset --hard

还有一些 remote 相关的操作。

之所以写成这么一坨的原因是因为避免出错,需要修改的只有三个地方,clone 地址,remote 地址,旧分支名称。那么是不是可以这么理解:

  • 如果前端写一个表单,就可以通过输入这三个内容太就可以完成者一系列操作了?
  • 更高级一点,这些信息原来放在 excel 里面,我也可以通过解析 excel 的方式拿到这三个信息,实现完全自动化?当然这个需要借助一点 node 的知识,但是不多。

这种纯体力劳动,越少手动操作越少犯错,而且仓库越多越能体现优势。

合并不同来源的分支

$ git merge master --allow-unrelated-histories

拉去远程覆盖本地

$ git reset --hard origin/master
$ git pull origin master

修改远程仓库地址

git remote set-url [--push] <name> <newurl> [<oldurl>]
git remote set-url --add [--push] <name> <newurl>
git remote set-url --delete [--push] <name> <url>

配置一个仓库对应多个远程仓库

如下,git里面的 config 文件长这样:

# .git/config
[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	symlinks = false
	ignorecase = true
	hooksPath = .husky
[remote "origin"]
	url = https://gitee.com/jci/datasource.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[remote "nlc"]
	url = https://github.com/DI-WEB/dataSource.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master
[branch "di/v_1.2"]
	remote = origin
	merge = refs/heads/di/v_1.2
[branch "di/dev-v1.2.2"]
	remote = nlc
	merge = refs/heads/di/dev-v1.2.2