git

2018.04.16 by jianfeng
1. 基础配置
官网链接
设置用户信息
在使用 Git 提交更改时,通常需要设置用户的姓名和电子邮件地址。
这些设置是全局的,意味着它们适用于系统上的所有 Git 存储库
git config --global user.name "your_name"
git config --global user.email "your_email@example.com"
创建 SSH key
SSH key是用于安全访问Git仓库的密钥对。在命令行中输入以下命令生成SSH key。
ssh-keygen -t rsa -C "邮箱地址"
在生成SSH key的过程中,可能需要输入一些信息或确认操作。完成后,SSH key将生成并保存在本地。(一般在用户主目录下的.ssh文件夹下)
最后,可以通过查看.gitconfig文件或使用git config user.name和git config user.email命令来检查配置是否成功。也可以直接使用git config --list来查看所有配置。
这些基础配置是使用Git进行版本控制的前提,确保在进行代码提交、仓库克隆等操作时能够正确识别和验证用户身份。
2. 本地操作
相关概念

| 名称 | 说明 |
|---|---|
| 工作区 | 实际开发目录,即当前目录 |
| 暂存区 | 临时保存已修改文件的区域(add命令后) |
| 版本库 | .git目录用于保存项目的元数据和对象数据库的地方 |
| master | 默认分支,即主分支 |
| HEAD | 指向当前分支的指针 |
三种状态

| 名称 | 英文 | 说明 |
|---|---|---|
| 已修改 | modified | 已修改表示修改了文件,但还没保存到数据库中 |
| 已暂存 | staged | 已暂存表示对一个已修改文件提交到暂存区 |
| 已提交 | committed | 已提交表示数据已经安全地保存在本地数据库中 |
常用命令
| 命令 | 说明 | 示例 |
|---|---|---|
| init | 初始化仓库 | git init |
| add | 添加文件到暂存区 | git add . |
| commit | 提交暂存区内容到版本库 | git commit -m '提交备注' |
| checkout | 切换分支或恢复文件 | git checkout . |
status | 查看当前仓库的状态 | git status |
| diff | 查看当前修改的内容(在提交前) | git diff |
| log | 查看提交历史 | git log |
reflog | 查看所有分支历史 | git reflog |
| reset | 回退版本 | git reset --hard HEAD^ |
rm | 删除文件 | git rm file_name |
clean | 删除未跟踪文件 | git clean -xdf |
| tag | 打标签 | git tag -a v1.0 -m 'v1.0' |
show | 查看标签信息 | git show v1.0 |
| stash | 临时保存修改 | git stash |
init
git init
# 初始化本地仓库,生成.git目录
git init --bare
# 初始化裸仓库,不包含工作目录的仓库。通常用于服务器端存储代码库
git init --initial-branch=main
# 初始化本地仓库,并指定主分支名称为main
add
提交修改/新文件
git add .
# 将文件的修改,文件的新建,添加到暂存区
git add -u (git add --updata)
# 将文件的修改、文件的删除,添加到暂存区
git add -A (git add --all)
# 将文件的修改,文件的删除,文件的新建,添加到暂存区
commit
git commit -m'提交备注'
#提交暂存区内容到版本库
git commit --amend
# 通常用于,提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令来重新提交:
checkout
git checkout .
# 放弃当前所有的本地修改
git checkout -b develop
# 创建develop分支,命令作用等同于git branch develop; git checkout develop
git checkout -- file
# 放弃file文件修改,回到最近一次git add或commit的状态
# 1. 若文件已经添加到暂存区,则该命令是回到暂存区状态。
# 2. 若文件没有添加到暂存区,则该文件回到版本库状态
git checkout tag_name
# 此时,提示 detached HEAD是因为tag相当于快照,是不能直接修改的
git checkout -b branch_name tag_name
# 基于该tag创建一个分支,这样就和普通分支一样可以操作了
git checkout -f branch_name
# 强制新建branch_name(即便该分支名称已经存在),我之前用它来操作(移动)branch_name指针
git checkout -b dev origin/dev
# 新建分支dev,且关联到远程分支origin/dev上
diff
查看当前修改的内容(在提交前)
git diff HEAD -- *.*
# 用来查看工作区和版本库里最新版的区别
log
查看历史提交信息(是从当前HEAD开始算起)
# 单行显示
git log --oneline --graph --all
reset
回退版本
git reset --hard HEAD^
# 回退上一个版本
git reset --hard HEAD^^
# 回退上上个版本
git reset --hard HEAD~100
# 回退上100个版本
stash
git stash
# 保存当前工作现场
git stash list
# 查看保存的工作现场
git stash pop
# 恢复工作现场
git stash apply
# 恢复工作现场,但是stash内容不删除
git stash apply stash@{0}
tag
查看标签
git tag
# 查看所有标签
git ls-remote --tags origin
# 查看远程标签
新建标签
git tag -a v1.0 [-m 'tag备注']
# 打标签,默认标签是打在最新提交的commit上的
git tag -a v1.0 17b6b9a
# 打标签,指定commit id
删除标签
git tag -d v1.0
# 删除标签
# 删除远程标签
git push origin :v1.0
推送标签到远程
git push origin v1.0
# 推送标签v1.0到远程仓库
git push origin --tags
# 推送所有标签到远程仓库
标签和分支关联操作
git checkout v1.0
# 切换到标签v1.0指向的版本
git branch [new-branch-name] v1.0
# 新建一个分支指向标签v1.0
git checkout -b bug v1.0
# 新建一个分支指向标签v1.0,并切换到该分支
3. 远程操作

常用命令
| 命令 | 说明 | 示例 |
|---|---|---|
clone | 克隆远程仓库 | git clone git@github.com:Orig5826/Basics.git |
| remote | 远程仓库操作 | git remote add origin git@github.com:Orig5826/Basics.git |
fetch | 从远程获取最新版本到本地(但不会自动merge) | git fetch origin master |
pull | 从远程获取最新版本并merge到本地(当服务器被他人更改时) | git pull origin master |
push | 推送本地库到远程库 | git push origin master |
remote
将本地仓库和GitHub上新建的仓库关联
git remote add origin git@github.com:Orig5826/Basics.git
# 添加远程库。origin常用远程库名称(可以修改)
git push -u origin master
# 将本地库中的内容推送到远程库中
git push origin master
# 推送本地库中的内容到远程库中
git remote show origin
# 查看远程库信息
假设远程仓库已经被删除,但是本地仓库还关联着远程仓库,此时需要解除关联。
# 查看远程分支
git branch -r
# 和远程仓库解除关联
git remote rm origin
同步处理
注意
本地分支和远程分支不一致的情况
# 先将远程分支更新到本地,但不合并
git fetch origin
# 然后查看下差异
git diff master origin/master
# 如需要,可以将远程分支合并到本地分支中
git merge origin/master
# 如果提示错误:fatal: refusing to merge unrelated histories。那么
# 加上如下命令,可以让两个不相干的分支强行合并
git merge origin/master --allow-unrelated-histories
# 最后push即可
git push origin master
4. 分支操作

常用命令
| 命令 | 说明 | 示例 |
|---|---|---|
| branch | 分支操作 | git branch dev |
| merge | 合并分支 | git merge repo1 |
| rebase | 变基(git rebase)是git中的一个强大命令,它用于改变一个分支的基点。简单 | git rebase -i HEAD~3 |
| cherry-pick | 选择性地合并分支 | git cherry-pick 17b6b9a |
branch
分支操作
git branch
# 查看本地所有分支
git branch -r
# 查看远程所有分支
git branch -a
# 查看所有分支(包括远程)
git branch dev
# 创建dev分支,但不切换。切换需要再执行git checkout dev
git branch -d dev
# delete a branch
git branch -D dev
# delete force
git branch -m [old_branch_name] new_branch_name
# remove/rename 修改当前分支名称 [修改旧分支名称为新分支名称]
git branch -vv
# 查看本地分支和远程分支的关联关系
# [-v] verbose / [-v -v = -vv]very verbose
git branch --set-upstream-to=origin/dev [dev]
# 将本地dev分支与远程origin/dev关联起来
git branch -u origin/dev [dev]
# 将本地dev分支与远程origin/dev关联起来
# 若当前分支就是dev,则可以省略[dev]参数
merge
以合并两个git仓库为例子,在想整合的仓库(即本仓库)路径下执行以下命令
# 备注:注意第4-5操作指令,是谁合并到了谁。
git remote add other repo_path
# 1. other为别名,repo_path为被合并的仓库路径。该命令本质上,相当于是将被合并的仓库当作远程仓库
git fetch other
# 2. 从repo_path中抓取数据到本仓库
git checkout -b repo1 other/master
# 3. 将repo_path仓库抓取的master分支作为新分支checkout到本地,新分支名称设置为repo1
git checkout master
# 4.切换为本仓库的master分支
git merge repo1
# 5. 将repo1合并到master
# 注意事项:
# 1.若merge的时候出现冲突,则需要先修改冲突。然后add,commit,push
# 2. 若merge出现unrelated history的警告,则需要在命令结尾添加--allow-unrelated-histories参数进行强行合并
- 拉取远程分支,并关联到本地分支
# [type 1] 创建并切换到dev分支,关联到远程origin/dev
git checkout -b dev origin/dev
# [type 2] 指令多了,但是和上面的功能是一样的
git checkout -b dev
git fetch origin dev
git merge origin/dev
rebase
变基(git rebase)是git中的一个强大命令,它用于改变一个分支的基点。简单来说,就是将一个分支上的所有提交应用到另一个分支上,并更新当前分支的基点。 一般应用于多人协作开发时,将别人的分支合并到自己的分支上。

git rebase -i HEAD~3
# 交互式变基,选择最近3次提交进行变基操作
git rebase -i 17b6b9a
# 交互式变基,选择commit-hash为17b6b9a的提交进行变基操作
cherry-pick
选择性地合并分支,优点是可以只合并某一个commit,而不是整个分支。
git cherry-pick 17b6b9a [commit-hash2]
# 选择性的合并某一个[或多个]commit到当前分支上
git cherry-pick -n 17b6b9a
# 选择性合并但不自动提交,需要手动执行add和commit操作
git cherry-pick --abort
# 如果cherry-pick失败了,可以使用这个命令恢复到merge之前的状态
git cherry-pick --continue
# 如果cherry-pick失败了,修复完冲突后使用该命令继续合并过程
5. 搭建git服务器
在linux上搭建git服务器
# 1. 安装git
# 2. 新建一个git用户,用来运行git服务
sudo adduser git
# 3. 创建证书登陆,即将客户端的id_rsa.pub导入进来,将公钥都放在/home/git/.ssh/authorized_keys文件中,一行一个(也可以后续在做该步骤)
# 4. cd到你所选定的目录下,初始化git仓库
sudo git init --bare ubuntu.git
# 5. 记得一定要修改所有者,要不然远程登陆肯定失败呀
sudo chown -R git:git ubuntu.git
# 6. 同时,可以考虑禁用shell登陆,方法可以是:将/etc/passwd文件中的git用户的shell做如此修改 =>/bin/bash -->/usr/bin/git-shell
# 此后,git用户可以正常通过ssh使用git,但无法登陆shell,因为我们为git用户指定的git-shell每一次登陆就自动推出
# 7. 客户端连接测试
git clone git@192.168.3.11:/home/git/ubuntu.git
# IP为服务器IP地址,端口默认为22
6. 大文件存储
LFS(Large File Storage)
# 安装LFS
git lfs install
# 跟踪*.bin文件,即大文件的扩展名
git lfs track "*.bin"
# 将.gitattributes文件添加到仓库中
git add .gitattributes
7. 其他操作
配置别名
- 查看状态
git config --global alias.st status
- 查看日志
git config --global alias.lg "log --oneline --graph --all"
当然了,为了让日志看起来更美观,可以这样配置:
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
忽略文件
- 直接在.gitignore文件中添加所需要忽略的文件/文件夹即可
10. 常见问题
merge时bin文件冲突
On branch feature
Your branch is up to date with 'origin/feature'.
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Changes to be committed:
modified: Demo/demo.h
modified: Demo/demo_spi.c
modified: Demo/demo_w25qxx.c
modified: Demo/main.c
modified: Source/drv_uart.c
modified: Source/drv_uart.h
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: demo.bin
从上述信息可知,分支feature与其他分支合并时,存在冲突, 其中 demo.bin 这个二进制文件在两个分支里都被修改了,从而产生冲突。 那么常见有几种解决方案
a. 手动选择版本
你可以手动选择保留当前分支(ours)或者合并分支(theirs)的 demo.bin 文件。
- 保留当前分支的版本
git checkout --ours demo.bin
git add demo.bin
git commit -m "Resolved demo.bin conflict, kept our version"
- 保留合并分支的版本
git checkout --theirs demo.bin
git add demo.bin
git commit -m "Resolved demo.bin conflict, kept their version"
b. 删除冲突的二进制文件
若 demo.bin 文件并非项目必需,或者你计划重新生成它,那么可以将其删除。
git rm demo.bin
git commit -m "Removed demo.bin due to merge conflict"
c. 配置 .gitattributes 以避免未来冲突
为防止将来再次出现 bin 文件的合并冲突,你可以在项目根目录下创建或编辑 .gitattributes 文件,然后添加如下内容:
*.bin merge=ours
这一配置表明在合并时,bin 文件会直接采用当前分支的版本。若你想采用合并分支的版本,可把 ours 替换成 theirs。 配置完成后,提交 .gitattributes 文件的更改:
git add .gitattributes
git commit -m "Configure merge strategy for bin files"
中止合并操作
要是你还没准备好解决冲突,或者想重新开始合并过程,可以中止当前的合并操作。
git merge --abort
解决SSL证书验证失败问题
# 当直接clone时,出现SSL证书验证失败的问题,导致无法克隆仓库。
git config --global http.sslVerify false # 临时关闭SSL证书验证
git clone <仓库地址>
git config --global http.sslVerify true # 恢复SSL证书验证
大文件上传问题
git push -u origin master
Locking support detected on remote "origin". Consider enabling it with:
$ git config lfs.https://.../info/lfs.locksverify true
Uploading LFS objects: 0% (0/1), 0 B | 0 B/s, done.
LFS: Client error ... (MISSING) from HTTP 413
error: failed to push some refs to 'git.wenjianfeng.top:apaki/godot_slg_demo.git'
经过确认,服务器端gitea已经开启了LFS支持,并且修改了app.ini配置文件,如下所示:
[lfs]
MAX_FILE_SIZE = 512M
但是,在客户端执行git push时仍然出现上述错误。因此修改nginx配置文件,如下所示:
# 默认nginx限制大小为1M
# 因此在http中添加如下配置,修改限制大小为512M
client_max_body_size 512M;
