Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Git stash pop仅在成功隐藏之前_Git_Bash - Fatal编程技术网

Git stash pop仅在成功隐藏之前

Git stash pop仅在成功隐藏之前,git,bash,Git,Bash,我的工作流程中有一部分涉及到以下方面: git隐藏更改 吉特拉力 流行音乐隐藏的变化 启动mergetool以解决冲突 我正在尝试编写一个脚本来同时完成所有这些事情,这样我就可以从终端调用它 #!/bin/bash # First stash our local changes git stash # Then git pull to update our repo git pull # Pop the stash git stash pop # Launch mergetool i

我的工作流程中有一部分涉及到以下方面:

  • git隐藏更改
  • 吉特拉力
  • 流行音乐隐藏的变化
  • 启动mergetool以解决冲突
我正在尝试编写一个脚本来同时完成所有这些事情,这样我就可以从终端调用它

#!/bin/bash

# First stash our local changes
git stash

# Then git pull to update our repo
git pull

# Pop the stash
git stash pop

# Launch mergetool if necessary
git mergetool

我遇到的问题是,如果我意外地运行了它,并且对隐藏没有任何更改,
git stash pop
会应用一些(通常是超旧的)隐藏。我想做的是运行
git stash pop
,前提是我之前确实隐藏了一些东西。有什么方法可以做到这一点吗?

如果你在脚本中做很多事情,你应该尽量避免隐藏,而不是简单地提交代码,然后拉取更改

您还可以编写别名而不是脚本:

git config --global alias.<your alias> "git add. && git commit &1 && git pull"
git-config——全局别名。“git add.&git commit&1&&git pull”

上面的命令将接受提交消息作为参数,并执行git add、commit和pull操作

首先运行git状态如何?如果有本地更改,请运行stash命令。如果没有,跳过它。将此结果保存在bool中,如果没有新的存储,则不要运行pop。

阅读您对为什么要这样做的解释,我可能会选择完全不同的方法。首先,我将获取您要使用的遥控器:

git fetch <remote> (e.g. git fetch origin)
这样,合并后就不会执行自动提交。

而且,可能更明智的做法是完全避免
git隐藏在这里。例如,我会考虑使用单独的
git fetch
git rebase
步骤(参见Xavier的回答),并注意到rebase现在有
--autostash
,它本质上就是做你想要的事情,只是不能通过
git pull
便利脚本直接使用。1

也就是说,有一种方法可以满足你的要求。这有点棘手。如果
git stash save
有一个类似于
git commit--allow empty
的“force”选项,这会容易得多,但它没有这样的选项。2相反,您可以做的是检测
git stash save
是否推送了一个新的存储。如果
git stash save
有一个退出状态,指示它是否推送了一个隐藏,那么这也会容易得多,但是它没有。这意味着我们必须完全依靠另一种伎俩。我们从两个事实开始:
git rev parse
从“引用”中查找SHA-1,而
git stash
使用一个特定的引用

git rev parse
命令将任何引用转换为SHA-1:

$ git rev-parse refs/remotes/origin/master
2635c2b8bfc9aec07b7f023d8e3b3d02df715344
引用只是一个名称,通常以
refs
开头,命名一些SHA-1 ID。最常见的是分支:
refs/heads/branch
。您可能还使用了标记:
refs/tags/tag
,并且可能使用了远程跟踪分支,如
origin/master
,它是全名的缩写,
refs/remotes/origin/master

stash
脚本使用
refs/stash
,因此我们可以简单地运行
git rev parse refs/stash
。3我们希望在
git stash save
之前运行它,然后在
git stash save
之后再次运行它。如果输出发生更改,那么
git stash save
步骤必须已将新的存储推送到存储堆栈上

我们必须小心一点,因为如果存储堆栈为空(因为上一个存储在较早时被弹出或删除,或者还没有创建任何存储),
git rev parse
将给出错误消息,并且不会生成SHA-1:

$ git rev-parse refs/stash
fatal: ambiguous argument 'refs/stash': unknown revision or path not in
the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

1
git pull
命令基本上是
git fetch
的简写,后跟
git merge
,或者,如果您告诉它,运行
git fetch
,后跟通常更合适的
git rebase
。但是,如果您将其分为两个单独的步骤,您将获得更多的控制权,以及在合并或重定基址之前检查传入更改的能力

2您可以使用相对较新的
create
store
子命令有效地强制创建隐藏:创建一个隐藏,然后存储生成的SHA-1,即使没有任何要隐藏的内容,您也可以强制保存一个隐藏。但并不是每个人都了解最新的git,所以对于脚本来说,使用旧的方式可能更明智(或者如前所述,完全不要使用隐藏,特别是在不同版本的git中,它有各种小但令人讨厌的bug)


3拼写全名是明智的,因为
git rev parse stash
将首先查找名为
stash
的分支。在编写别名或脚本时,所有引用通常都是这样:拼写全名(并根据需要使用
--
语法),以确保git在奇数情况下不会执行其认为的操作。

使用
git stash save
时,成功保存后将显示您传递的消息

因此,一个技巧是生成一个时间戳,它将用作消息,如果在生成的消息中找到了时间戳,则丢弃最近的隐藏

一行:

t=timestamp-$(date +%s); r=$(git stash save $t); v=$(echo $r|grep $t); if [ "$v" ]; then git stash list; echo "SAVED! NOW REMOVING..."; git stash drop stash@{0}; else echo "Nothing to Stash!"; fi; echo "Stashes: "; git stash list; echo "Done!"
扩大:

# unique timestamp
t=timestamp-$(date +%s) 

# stash with message
r=$(git stash save $t)

# check if the value exists
v=$(echo $r|grep $t)

# if the message is found...
if [ "$v" ] then 

  # DEBUG: Before
  git stash list
  echo "SAVED! NOW REMOVING..."

  # remove last stash
  git stash drop stash@{0}
else 
  echo "Nothing to Stash!"
fi

# DEBUG: after
echo "Stash List: "
git stash list
echo "Done!"

我正在寻找类似的东西来自动合并主。我最终只是创建了一个具有唯一名称的空文件。下一步是在隐藏时包括未跟踪的文件(
stash-u
)。现在我知道我可以随时弹出,因为我正在创造一些东西来隐藏。最后,我删除了我创建的新文件,其他的都完成了

然后,我创建了以下别名:

 up  - pull with rebase and sub-modules*
 mm  - merge master
 tm  - create file with novel name
 rtm - remove said file
…以及实际别名:

[alias]
up           = !git pull --rebase --prune --recurse-submodules $@ && git submodule update --init --recursive && git submodule foreach git up && echo 'git on up'
mm           = "!f() { git tm; git stash -u; git co ${1-master}; git up; git co -; git merge ${1-master}; git stash pop; git rtm; }; f"
tm           = "!f() { touch __nothing_to_see_here__; }; f"
rtm          = "!f() { rm __nothing_to_see_here__; }; f"

*up from

为什么需要隐藏步骤?如果我有与拉取冲突的本地更改,它会显示“错误:您对以下文件的本地更改将被合并覆盖:file.ext请提交更改或在合并之前将其隐藏。中止”。因此,隐藏、拉取,pop way允许我拉取更改,然后通过mergetool将其合并。那么为什么不简单呢
# unique timestamp
t=timestamp-$(date +%s) 

# stash with message
r=$(git stash save $t)

# check if the value exists
v=$(echo $r|grep $t)

# if the message is found...
if [ "$v" ] then 

  # DEBUG: Before
  git stash list
  echo "SAVED! NOW REMOVING..."

  # remove last stash
  git stash drop stash@{0}
else 
  echo "Nothing to Stash!"
fi

# DEBUG: after
echo "Stash List: "
git stash list
echo "Done!"
 up  - pull with rebase and sub-modules*
 mm  - merge master
 tm  - create file with novel name
 rtm - remove said file
[alias]
up           = !git pull --rebase --prune --recurse-submodules $@ && git submodule update --init --recursive && git submodule foreach git up && echo 'git on up'
mm           = "!f() { git tm; git stash -u; git co ${1-master}; git up; git co -; git merge ${1-master}; git stash pop; git rtm; }; f"
tm           = "!f() { touch __nothing_to_see_here__; }; f"
rtm          = "!f() { rm __nothing_to_see_here__; }; f"