如何仅暂存多个更改文件中的一个文件
技术背景
在使用Git进行版本控制时,我们经常会在一个工作分支上同时对多个文件进行修改。有时,我们可能只想暂存其中一个或几个文件的更改,而将其他文件的更改保留在工作区。然而,Git的基本git stash命令默认会暂存所有已修改和已暂存的文件,这就需要一些特定的方法来实现仅暂存部分文件的需求。
实现步骤
方法一:使用git stash push(Git 2.13及以上版本)
- 确定要暂存的文件路径。
- 执行以下命令暂存指定文件:
1
| git stash push [-m <message>] [--] [<pathspec>...]
|
例如,要暂存path/to/file文件,可以使用以下命令:
1
| git stash push path/to/file
|
如果需要添加暂存信息,可以使用-m参数:
1
| git stash push -m "Stash changes for path/to/file" path/to/file
|
方法二:使用git stash -p进行交互式暂存
- 执行以下命令开始交互式暂存:
1
| git stash push -p -m "my commit message"
|
- 对于每个代码块(hunk),Git会提示你选择操作:
y:暂存此代码块。n:不暂存此代码块。q:退出,不暂存此代码块及后续代码块。a:暂存此代码块及文件中后续的所有代码块。d:不暂存此代码块及文件中后续的所有代码块。g:选择要跳转到的代码块。/:搜索匹配给定正则表达式的代码块。j:保留此代码块不做决定,查看下一个未决定的代码块。J:保留此代码块不做决定,查看下一个代码块。k:保留此代码块不做决定,查看上一个未决定的代码块。K:保留此代码块不做决定,查看上一个代码块。s:将当前代码块拆分为更小的代码块。e:手动编辑当前代码块。?:打印帮助信息。
方法三:使用diff、checkout和apply
- 创建一个差异文件:
1
| git diff path/to/dir > stashed.diff
|
- 恢复文件到HEAD版本:
1
| git checkout path/to/dir
|
- 之后,如果需要恢复暂存的更改,可以使用以下命令:
方法四:临时提交不需要暂存的文件
- 临时提交不需要暂存的文件:
1 2
| git add <files you don't want to stash> git commit -m "temp"
|
- 暂存其他文件:
1
| git stash save "stash message"
|
- 撤销临时提交:
1 2
| git reset --soft HEAD^ git reset
|
核心代码
使用git stash push
1
| git stash push path/to/file
|
使用git stash -p
1
| git stash push -p -m "my commit message"
|
使用diff、checkout和apply
1 2 3
| git diff path/to/dir > stashed.diff git checkout path/to/dir git apply stashed.diff
|
临时提交不需要暂存的文件
1 2 3 4 5
| git add <files you don't want to stash> git commit -m "temp" git stash save "stash message" git reset --soft HEAD^ git reset
|
最佳实践
- 使用最新版本的Git:如果你的Git版本支持
git stash push,建议优先使用该命令,因为它可以直接指定要暂存的文件,操作简单。 - 交互式暂存:当你需要精确控制暂存的代码块时,可以使用
git stash -p进行交互式暂存。 - 备份差异文件:使用
diff、checkout和apply方法时,建议将差异文件保存到一个安全的位置,以免丢失。
常见问题
使用git stash --keep-index的问题
git stash --keep-index会将所有未添加的文件和已暂存的文件都暂存起来,即使使用了--keep-index选项,也可能会导致后续合并冲突。因此,不建议使用该方法来仅暂存部分文件。
diff、checkout和apply方法的二进制文件问题
如果要暂存的文件包含二进制文件(如PNG图片),git diff生成的差异文件可能无法正确保存二进制文件的更改。在这种情况下,建议使用其他方法。
暂存未跟踪文件
如果要暂存的文件是未跟踪的文件,需要先将其添加到暂存区,然后再进行暂存操作。例如:
1 2
| git add <untracked_file> git stash push <untracked_file>
|