git stash
保存没有提交的修改
git stash暂存
git stash pop 使用最近一次暂存
git stash save "xxx" 暂存时添加暂存信息
git stash list 查看暂存列表
git stash apply stash@{X} 回到某个暂存版本
git stash drop stash@{X} 删除某个暂存版本
git stash show stash@{X} 查看暂存版本详情
git stash branch 从最新的stash创建分支
示例:stash2个版本代码,然后查看stash版本列表,应用其中一个版本,删除其中一个版本。
libo@libodeMacBook-Pro AlgorithmDeep % git stash list
libo@libodeMacBook-Pro AlgorithmDeep % git stash save "添加一个功能1"
Saved working directory and index state On master: 添加一个功能1
libo@libodeMacBook-Pro AlgorithmDeep % git stash save "删除了一个功能2"
Saved working directory and index state On master: 删除了一个功能2
libo@libodeMacBook-Pro AlgorithmDeep % git stash list
stash@{0}: On master: 删除了一个功能2
stash@{1}: On master: 添加一个功能1
libo@libodeMacBook-Pro AlgorithmDeep % git stash apply stash@{1}
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .idea/vcs.xml
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/src/main/java/com/example/algorithmdeep/Practise.java
libo@libodeMacBook-Pro AlgorithmDeep % git stash drop stash@{0}
Dropped stash@{0} (3c4d22d1252eb2f067ad2f30cff69f72dfff3672)
libo@libodeMacBook-Pro AlgorithmDeep % git stash list
stash@{0}: On master: 添加一个功能1
git reset
git reset 命令格式为:
git reset [ --soft | --mixed | --hard ] [< commitid >]
soft:
–soft参数只将其它的commit重置到你选定的HEAD,index和working copy中的数据不变。
mixed:
–mixed参数是将HEAD和index重置到你选定的HEAD,而working copy不变。
hard:
–hard是将HEAD,index,working copy同时改变到你规定的commit上。
示例:抛弃工作区间不需要改动,代码回到上一次提交状态:
libo@libodeMacBook-Pro AlgorithmDeep % git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: .idea/vcs.xml
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: app/src/main/java/com/example/algorithmdeep/Practise.java
libo@libodeMacBook-Pro AlgorithmDeep % git reset --hard
HEAD is now at 828b07b init commit
git log
- git log 查看各次提交信息
libo@libodeMacBook-Pro AlgorithmDeep % git log
commit 4a0a889808b21db5ec2c056209ceaf1bd7e34abf (HEAD -> master)
Author: libo <libo31@xiaomi.com>
Date: Sun Nov 26 11:10:09 2023 +0800
新增detectCycle代码
commit 8804579282019db1def1d4ec5a0970a445c18daa
Author: libo <libo31@xiaomi.com>
Date: Sun Nov 26 11:09:05 2023 +0800
新增levelOrder代码
commit 828b07b94e9598f5442f452f734bcecbc3cdfd3a
Author: libo <libo31@xiaomi.com>
Date: Sun Nov 26 10:53:27 2023 +0800
init commit
- git log --oneline 选项来查看历史记录的简洁的版本
libo@libodeMacBook-Pro AlgorithmDeep % git log --oneline
4a0a889 (HEAD -> master) 新增detectCycle代码
8804579 新增levelOrder代码
828b07b init commit
合并多个commit
方法:git rebase
# 查看前10个commit
git log -10
# 运行 `git rebase` 命令,并指定需要合并的提交范围。如果你想要合并最近的 3 个提交,可以使用以下命令:
git rebase -i HEAD~3
或者
git rebase -i 开始commit 结束commit
# 强制push以替换远程仓的commitID
git push --force
参考:https://blog.csdn.net/wangdawei_/article/details/131669124
git rebase -i HEAD~2
pick 8804579 新增levelOrder代码
pick 4a0a889 新增detectCycle代码
# Rebase 828b07b..4a0a889 onto 828b07b (2 commands)
Successfully rebased and updated refs/heads/master.
git diff
用于比较两次修改的差异
1.1 比较工作区与暂存区
git diff 不加参数即默认比较工作区与暂存区
1.2 比较暂存区与最新本地版本库(本地库中最近一次commit的内容)
git diff --cached [<path>...]
1.3 比较工作区与最新本地版本库
git diff HEAD [<path>...] 如果HEAD指向的是master分支,那么HEAD还可以换成master
1.4 比较工作区与指定commit-id的差异
git diff commit-id [<path>...]
1.5 比较暂存区与指定commit-id的差异
git diff --cached [<commit-id>] [<path>...]
1.6 比较两个commit-id之间的差异
git diff [<commit-id>] [<commit-id>]
1.7 比较两个分支上最后 commit 的内容的差别
git diff <分支名1> <分支名2>
参考:https://www.runoob.com/git/git-diff.html
git commit --amend
合并这次提交到上一次commit里面,并且可以修改commit message。
新增detectCycle代码
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# Date: Sun Nov 26 11:10:09 2023 +0800
#
# On branch master
# No commands done.
# Next command to do (1 remaining command):
# pick 4a0a889 新增detectCycle代码
# You are currently editing a commit during a rebase.
#
# Changes to be committed:
# modified: app/src/main/java/com/example/algorithmdeep/Practise.java
:wq
git cherry-pick
cherry-pick命令常用于以下场景:
1.合并单个提交:当我们只想应用某个分支上的一个提交到当前分支时,可以使用cherry-pick命令,而不需要合并整个分支。
2.修复bug:当我们在一个分支上修复了一个bug,并希望将这个修复应用到其他分支上时,可以使用cherry-pick命令。
3.提取特定功能:当我们在一个分支上开发了一个新功能,并希望将该功能应用到其他分支上时,可以使用cherry-pick命令。
git cherry-pick <commit>
示例:在主分支新增了提交,在feature分支使用git cherry-pick <commit>去拉取合并这一个提交。
libo@libodeMacBook-Pro AlgorithmDeep % git branch feature
libo@libodeMacBook-Pro AlgorithmDeep % git commit -a -m "主分支提交功能"
[master 00e8af2] 主分支提交功能
1 file changed, 4 insertions(+)
libo@libodeMacBook-Pro AlgorithmDeep % git checkout feature
Switched to branch 'feature'
libo@libodeMacBook-Pro AlgorithmDeep % git cherry-pick 00e8af2
[feature e0017ec] 主分支提交功能
Date: Sun Nov 26 11:40:27 2023 +0800
1 file changed, 4 insertions(+)
git merge和git rebase
git rebase和git merge这两个命令都旨在将更改代码从一个分支合并到另一个分支,但二者的合并方式却有很大的不同。
Git merge 将两个分支中的所有提交都合并到一起,并创建一个新的合并提交,保留了历史记录。这导致了 Git 历史记录中出现多个分支合并点的情况,从而使历史记录更加复杂。
Git rebase 是将一个分支的提交序列“拉直”,并且将其与另一个分支合并。这意味着,提交历史看起来好像是一条直线,没有分叉,因此整个提交历史看起来更加整洁,历史记录保持相对简单。
总的来说,Git rebase 可以提供更整洁的提交历史,但它需要更多的注意力和精细的操作,因为它可能导致原有的提交变得不可用。Git merge 则是更为保守的合并方法,它更简单,但历史记录更加复杂。因此,选择哪种方法取决于团队和项目的需求和偏好。
场景:
假设当前我们有master和feature分支,当你在专用分支上开发新 feature 时,然后另一个团队成员在 master 分支提交了新的 commits,这种属于正常的Git工作场景。
此时是无法push到远程仓库的,需要进行分支合并,下面来演示git rebase 和 git merge 这两个命令的差异。
1、git merge
操作:
git checkout feature
git merge master
由上图可知,git merge 会在 feature 分支中新增一个新的 merge commit,然后将两个分支的历史联系在一起
- 使用 merge 是很好的方式,因为它是一种非破坏性的操作,对现有分支不会以任何方式被更改。
- 另一方面,这也意味着 feature 分支每次需要合并上游更改时,它都将产生一个额外的合并提交。
- 如果master 提交非常活跃,这可能会严重污染你的 feature 分支历史记录。
2. git rebase
git checkout feature
git rebase master
-
rebase 会将整个 feature 分支移动到 master 分支的顶端,从而有效地整合了所有 master 分支上的提交。
-
与 merge 提交方式不同,rebase 通过为原始分支中的每个提交创建全新的 commits 来重写项目历史记录,特点是仍然会在feature分支上形成线性提交
-
rebase的主要好处就是历史记录更清晰,没有不必要的合并提交,提交历史看起来好像是一条直线,没有分叉。
libo@libodeMacBook-Pro AlgorithmDeep % git checkout feature
Switched to branch 'feature'
libo@libodeMacBook-Pro AlgorithmDeep % git rebase master
Auto-merging app/src/main/java/com/example/algorithmdeep/Practise.java
CONFLICT (content): Merge conflict in app/src/main/java/com/example/algorithmdeep/Practise.java
error: could not apply 4a0a889... 新增detectCycle代码
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 4a0a889... 新增detectCycle代码
Could not apply 53a0a17... feature分支提交功能3
libo@libodeMacBook-Pro AlgorithmDeep % git rebase --continue
app/src/main/java/com/example/algorithmdeep/Practise.java: needs merge
You must edit all merge conflicts and then
mark them as resolved using git add
libo@libodeMacBook-Pro AlgorithmDeep % git add .
libo@libodeMacBook-Pro AlgorithmDeep % git rebase --continue
[detached HEAD 17fcbb1] feature分支提交功能3
1 file changed, 5 insertions(+)
Successfully rebased and updated refs/heads/feature.
rebase之后,两个分支的两个条线,就融合成了一条提交线:
如何选择git merge和git rebase?
git merge优点是分支代码合并后不破坏原分支的代码提交记录,缺点就是会产生额外的提交记录并进行两条分支的合并,
git rebase 优点是无须新增提交记录到目标分支,rebase后可以将对象分支的提交历史续上目标分支上,形成线性提交历史记录,进行review的时候更加直观
git merge 如果有多人进行开发并进行分支合并,会形成复杂的合并分支图,比如:
总结:
融合个人分支到主分支的时使用git merge,而不用git rebase
融合主分支到个人分支的时候使用git rebase,可以不污染分支的提交记录,形成简洁的线性提交历史记录。
网友评论