Git 代码管理
Git 基本概念
- 文件状态
- 未跟踪(Untracked)
- 未修改(Unmodified)
- 已修改(Modified)
- 暂存区(Staged)
- 三个工作区域
- 工作区(Working Directory)
- 暂存区(Staging Area)
- 仓库区(Repository)
- 工作树(Worktree)
@startuml
scale 4
participant 未跟踪 as Ut
participant 暂存区 as S
participant 未修改 as Um
participant 已修改 as M
Ut -> S: 添加到暂存区
Um -> M: 编辑文件
M -> S: 添加到暂存区
S -> Ut: 移出暂存区
@enduml
Git 工作流程
@startuml
scale 3
participant 工作区 as work
participant 暂存区 as stage
participant "仓库区(本地)" as rep
participant "仓库区(远程)" as github
group 工作区
work -> stage: 添加、修改:git add 文件或目录
work <- stage: 删除: git rm 文件
work <- stage: 恢复内容: git checkout 文件
end group
group 版本库
stage -> rep: 保存一小段的工作内容: git commit -m "备注"
rep -> stage: 回退到某个记录中: git reset 版本号
end group
group 服务器
rep -> github: 同步本地仓库到服务器: git push
github -> rep: 同步服务器到本地仓库: git pull
end group
@enduml
Git 常用命令
基于 Git 的远程仓库
远程仓库 | 地址 | 备注 |
---|---|---|
GitHub | https://github.com/ | 世界上最主流的远程开源仓库。 |
Gitee | https://gitee.com/ | 国内目前比较主流的开源仓库,也可以私有化部署。 (推荐) |
GitLab | https://gitlab.com/ | 私有化部署,企业使用较多。 |
Git 同步命令
克隆远程仓库
- 命令:
git clone <url>
远程连接方式 | 特点 |
---|---|
HTTPS 连接 | 使用给定 URL 即可 clone,在 push 时验证用户名和密码。 |
SSH 连接 | 需要提前添加 SSH Key,在 push 时不需要输入用户名,配置 SSH 时设置了密码才需要输入密码。(一般具有私有性的推荐用ssh) |
HTTPS 连接进行配置
- 配置全局帐号:
- 配置用户名:
git config --global user.name "your name"
- 配置邮箱:
git config --global user.email "your_email@youremail.com"
- 配置用户名:
- 验证配置结果:
git config --global --list
SSH 连接进行配置
- 生成 SSH Key:
ssh-keygen -t rsa -C "your_email@youremail.com"
- 连敲三次回车键。(不要输入密码,不然以后每次都要输密码)
- 到对应目录下找生成的公钥和密钥。
- 把公钥配置到远程仓库。打开公钥文件-L>复制->登陆远程仓库->头像->设置 → SSH公钥->粘贴到公钥一栏
sshkey生成目录
sshkey文件
拉取远程仓库
- 拉取远程仓库到本地:
git pull
localhost@ git_demo % git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From gitee.com:xxxx/git_demo
3c18462..9e58263 master -> origin/master
Updating 3c18462..9e58263
Fast-forward
README.md | 2 ++
1 file changed, 2 insertions(+)
初始化仓库
- 在已存在的目录中初始化仓库(空仓库):
git init
- 关联远程仓库:
git remote add origin <url>
784f439064aa@ git_demo % git init
Initialized empty Git repository in /Users/mac/git_demo/.git/
localhost@ git_demo % git remote add origin git@gitee.com:feier-hogwarts/git_demo.git
localhost@ git_demo % git pull --allow-unrelated-histories origin master(在连接完远程仓库和本地仓库后第一次同步的时候需要执行的命令)
remote: Enumerating objects: 17, done.
remote: Counting objects: 100% (17/17), done.
remote: Compressing objects: 100% (16/16), done.
remote: Total 17 (delta 3), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (17/17), done.
From gitee.com:feier-hogwarts/git_demo
* branch master -> FETCH_HEAD
* [new branch] master -> origin/master
Git 修改命令
跟踪新文件
- 添加文件或目录到暂存区:
git add <file>/<directory>
# 跟踪某个文件
784f439064aa@ git_demo % git add new_file.txt
# 跟踪当前目录下所有文件
784f439064aa@ git_demo % git add .
提交更新
- 提交到本地仓库:
git commit -m "comments"
- 已修改文件跳过使用暂存区域:(同时执行add和commit)
git commit -a -m "comments"
784f439064aa@ git_demo % git commit -m "first upload"
[master (root-commit) 9868463] first upload
1 file changed, 3 insertions(+)
create mode 100644 readme.txt
784f439064aa@ git_demo % git commit -a -m "跳过使用暂存区"
[master 2fee19e] 跳过使用暂存区
1 file changed, 2 insertions(+)
注意:第一次提交的时候需要 git push --set-upstream origin master建立本地分支与远程分支的联系
推送到远程仓库
- 推送本地仓库到远程仓库:
git push
localhost@ git_demo % git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 325 bytes | 325.00 KiB/s, done.
Total 3 (delta 1), reused 2 (delta 1)
remote: Powered by GITEE.COM [GNK-6.4]
To gitee.com:feier-hogwarts/git_demo.git
a1cbb3a..3c18462 master -> master
Git 常用调试命令
查看文件状态 git status
784f439064aa@ git_demo % git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: readme.txt
查看提交历史 git log
- git log -n 3:查看最近三次的提交
- git log --since=‘2 weeks’:只显示2周依赖的提交
查看已暂存和未暂存的修改 git diff
- 比较当前文件和暂存区域快照之间的差异:
git diff
- 查看已暂存的将要添加到下次提交里的内容:
git diff --staged
784f439064aa@ git_demo % git diff
diff --git a/readme.txt b/readme.txt
index f971b3a..bfa1ab8 100644
--- a/readme.txt
+++ b/readme.txt
@@ -3,3 +3,5 @@
update1
update2
+
+update3
784f439064aa@ git_demo % git diff --staged
diff --git a/new_file.txt b/new_file.txt
new file mode 100644
index 0000000..c855c19
--- /dev/null
+++ b/new_file.txt
@@ -0,0 +1 @@
+987655
撤销操作 git checkout
和 git reset
- 撤销对文件的修改:
git checkout <file>
- 取消暂存(撤销add):
git reset HEAD <file>
784f439064aa@ git_demo % cat readme.txt
1234
update1
update2
update3
784f439064aa@ git_demo % git checkout readme.txt
784f439064aa@ git_demo % cat readme.txt
1234
update1
update2
784f439064aa@ git_demo % git reset HEAD file.txt
784f439064aa@ git_demo % git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
file.txt
nothing added to commit but untracked files present (use "git add" to track)
移除文件 git rm
- 删除文件(本地和暂存区都不想要):
git rm -f <file>
- 移出暂存区:
git rm --cached <file>
784f439064aa@ git_demo % git rm -f file.txt
rm 'file.txt'
784f439064aa@ git_demo % git rm --cached file.txt
rm 'file.txt'
忽略文件
-
.gitignore
文件。(隐藏文件,用ls -al可以找到) - 有些文件无需纳入 Git 的管理。
- 比如日志文件,或者编译过程中创建的临时文件。
如何创建?
touch .gitignore
vim .gitignore
/文件夹/*
.vscode
.idea
log/*
*.pyc
*.libspec
*test.robot
export/*
==GitLab 实战(见git代码管理L2)==
==GitHub 实战(见git代码管理L2)==
==Gitee 实战(见git代码管理L2)==
==Git 客户端与 IDE 实战(见git代码管理L2)==
Git Log 分析与检索
Git Log 分析
- 查看项目历史信息:
git log
git log
commit 0ba2badd7f0d7e3c245f6ebd2237f7aabaaea1ca (HEAD -> master, origin/master, origin/hogwarts, dev)
Author: hogwarts_feier <fangyuan@ceshiren.com>
Date: Fri Feb 24 14:19:52 2023 +0800
添加忽略文件
commit 4c086e144ea974d5fca3d0c23db4022990c2d511
Author: hogwarts_feier <fangyuan@ceshiren.com>
Date: Fri Feb 24 14:08:22 2023 +0800
添加 newfile 文件
commit cb8445d3d016397dead9e7f572bbf778076e7c5f
Author: hogwarts_feier <fangyuan@ceshiren.com>
Date: Fri Feb 24 14:05:06 2023 +0800
删除
commit ca61f2dca670724820ad498ac167ff8de5f8331a
Author: hogwarts_feier <fangyuan@ceshiren.com>
Date: Fri Feb 24 13:53:40 2023 +0800
Git Log 检索
- 筛选时间:
git log --since='2023-02-02 00:00:00'
- 筛选作者:
git log --author='feier'
- 筛选描述:
git log --grep='update'
git_demo % git log --since='2023-02-02 00:00:00'
commit 0ba2badd7f0d7e3c245f6ebd2237f7aabaaea1ca (HEAD -> master, origin/master, origin/hogwarts, dev)
Author: hogwarts_feier <xxx@ceshiren.com>
Date: Fri Feb 24 14:19:52 2023 +0800
添加忽略文件
git log --author='feier'
commit 0ba2badd7f0d7e3c245f6ebd2237f7aabaaea1ca (HEAD -> master, origin/master, origin/hogwarts, dev)
Author: hogwarts_feier <xxx@ceshiren.com>
Date: Fri Feb 24 14:19:52 2023 +0800
添加忽略文件
git log --grep='update'
commit da76565755c86a68123640ff7729f0796734acd3
Author: hogwarts_feier <xxx@ceshiren.com>
Date: Fri Feb 24 03:43:42 2023 +0000
update 1.
Signed-off-by: hogwarts_feier <xxx@ceshiren.com>
分支管理策略
分支管理
- 概念:
- 每次提交,Git 都把它们串成一条时间线,这条时间线就是一个分支。
- 价值:
- 多人协作。
- 环境管理。
创建分支
- 新建分支,但仍然停留在当前分支:
git branch 分支名
- 新建分支并直接切换至该分支:
git checkout -b 分支名
查看分支
- 列出所有本地分支:
git branch
- 列出所有远程分支:
git branch -r
- 列出所有本地与远程分支:
git branch -a
切换分支
- 切换到指定分支:
git checkout 分支名
删除分支
- 删除指定分支:
git branch -d 分支名
Git 合并与冲突
合并分支
- 合并指定分支到当前分支:
git merge 其他分支 本分支
- 变基:重新设置基准:
git rebase 其他分支
解决冲突
-
解决冲突方式:
- IDE 中解决冲突:选择要保留的内容点击 Accept,保存代码。
- 文件中解决冲突:保留需要的内容,删除其余内容,去掉分割线,保存代码。
<<<<<<< (本地修改内容) ======= (远程修改内容) >>>>>>>
-
冲突解决流程:
- 在本地当前分支上,修改冲突内容。
- 执行
git add .
添加到暂存区。 - 执行
git commit -m '提交说明'
提交到本地仓库,完成合并。 - 执行
git push
提交到远程仓库。
提交代码并解冲突的完整步骤
-
拉取别人的代码:
- git check xxx # 切到xxx的支线
- git pull # 拉取xxx的代码
=
- git fetch # 拉取所有人的支线
-
git merge xxx # 合并xxx的支线代码
origin/xufangyi:git status(add,commit,push) , git checkout master/xxx
origin/master:git pull,git checkout xufangyi
origin/xufangyi:git merge master/xxx,解冲突,(add,commit,push)
常见问题
-
git pull将远程代码与本地代码合并时,显示Already up to date但是本地文件夹并没有更新?
可能原因一:代码有修改的部分,没有commit。看看可不可以先commit,然后再执行我的操作。
可能原因二:
解决方法:1. 放弃所有的缓存:git reset HEAD .
2. 放弃掉所有还没有加入到缓存区(git add)的修改:git checkout .
3. 然后重新pull:git pull -
查看git init 后当前文件夹下没有生成.git文件
解决方法:查看->勾选隐藏项目
-
fatal: Unable to create ‘D:/HDM2/.git/index.lock’: File exists.
$ git checkout xufangyi fatal: Unable to create 'D:/HDM2/.git/index.lock': File exists. Another git process seems to be running in this repository, e.g. an editor opened by 'git commit'. Please make sure all processes are terminated then try again. If it still fails, a git process may have crashed in this repository earlier: remove the file manually to continue.
解决方法:删除掉index.lock文件
-
有时merge了主线,部分脚本或文件被直接覆盖,并不是所有的冲突都显示出来
解决方法:因为git具有自动合并变更的功能,一般是简单冲突可能就被自动合并了,一些离得相近或相似的代码git做不出判断,会显示冲突。只要在merge前提交代码,如果遇到脚本被覆盖可以通过
git log
命令查看提交历史,找到你想要回退到的版本号,然后使用git checkout
命令切换到该版本,你就可以恢复被覆盖之前的代码。且注意:push只会提交修改的文件,merge也只会合并修改的文件与主线上对应的文件,所以本地未修改单文件是安全的。
-
如果你是在合并主线之后且已经在新的脚本上做了修改之后才发现你的脚本被覆盖,可你可以做以下操作:
-
备份当前工作:在采取任何操作之前,确保备份你当前的工作。
-
查看历史记录:使用
git log
命令查看提交历史,找到之前脚本的版本。 -
回滚到之版本:使用
git checkout
命令将你的工作区回滚到之前的脚本版本。 -
合并新脚本:将你之前修改过的新脚本复制回到工作区。
-
重新测试并提交。
-
-