New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve pre-push file list when merges are involved #860
Comments
Hmmm, the three dots here are supposed to avoid merge commits. I'm also not sure:
and I really don't think I'd want to take on that complexity for a feature that would only be used very rarely ( So basically: convince me this is a problem worth fixing, convince me it'll not add significant complexity / special snowflakes, convince me it can't (easily) be done in hooks themselves :) |
Regarding the current use of Good points, here's my attempt at addressing them:
One option is a per-hook configuration: Another option is just top level overall.
I think something simpler would be most convenient, matching
We can simplify and just do
Use the remote of the current branch's upstream. If it does exist locally, use the upstream version of that branch. Error if it doesn't exist in whatever remote we use.
I think the
Use the upstream version of the branch.
If pushing to the branch, do the diff with whatever is upstream like Summary:
And to reiterate, I think the use-case here is:
|
The way you describe it should already be the existing behaviour. Since the commits in |
I see. I linked an example repo above:
|
I had trouble following your example so I created a script: script#!/usr/bin/env bash
set -euxo pipefail
rm -rf upstream clone
git init upstream
git -C upstream commit --allow-empty -m 'Initial commit'
git -C upstream config receive.denyCurrentBranch ignore
git clone upstream clone
cd clone
cat > .pre-commit-config.yaml <<EOF
repos:
- repo: local
hooks:
- id: echo
name: echo
entry: echo
verbose: true
language: system
stages: [push]
EOF
git add .pre-commit-config.yaml
pre-commit install -t pre-push
git commit -m "Add push"
git push origin HEAD
touch master_only_file
git add master_only_file
git commit -m "Add master_only_file"
git push origin HEAD
git checkout origin/master^ -b bar
touch bar
git add bar
git commit -m "Add bar"
git merge origin/master --no-edit
git log --oneline --graph --decorate
: merge base
mb="$(git merge-base origin/master HEAD)"
git diff "${mb}" HEAD --name-only
: commits to push
git rev-list HEAD --topo-order --reverse --not --remotes=origin |
xargs git show
: source vs origin calculation
first_ancestor=$(
git rev-list HEAD --topo-order --reverse --not --remotes=origin |
head -1
)
source="$(git rev-parse "${first_ancestor}^")"
git show "${source}"
git diff --name-only "${source}...HEAD"
git push origin HEAD output$ bash t.sh
+ rm -rf upstream clone
+ git init upstream
Initialized empty Git repository in /tmp/t/upstream/.git/
+ git -C upstream commit --allow-empty -m 'Initial commit'
[master (root-commit) 50bebbc] Initial commit
+ git -C upstream config receive.denyCurrentBranch ignore
+ git clone upstream clone
Cloning into 'clone'...
done.
+ cd clone
+ cat
+ git add .pre-commit-config.yaml
+ pre-commit install -t pre-push
pre-commit installed at /tmp/t/clone/.git/hooks/pre-push
+ git commit -m 'Add push'
[master 625ef71] Add push
1 file changed, 9 insertions(+)
create mode 100644 .pre-commit-config.yaml
+ git push origin HEAD
echo.....................................................................Passed
hookid: echo
.pre-commit-config.yaml
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 354 bytes | 354.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /tmp/t/upstream
50bebbc..625ef71 HEAD -> master
+ touch master_only_file
+ git add master_only_file
+ git commit -m 'Add master_only_file'
[master bbcf4f2] Add master_only_file
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master_only_file
+ git push origin HEAD
echo.....................................................................Passed
hookid: echo
master_only_file
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 306 bytes | 306.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /tmp/t/upstream
625ef71..bbcf4f2 HEAD -> master
+ git checkout 'origin/master^' -b bar
Switched to a new branch 'bar'
+ touch bar
+ git add bar
+ git commit -m 'Add bar'
[bar 90ef098] Add bar
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 bar
+ git merge origin/master --no-edit
Merge made by the 'recursive' strategy.
master_only_file | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 master_only_file
+ git log --oneline --graph --decorate
* aabbc0a (HEAD -> bar) Merge remote-tracking branch 'origin/master' into bar
|\
| * bbcf4f2 (origin/master, origin/HEAD, master) Add master_only_file
* | 90ef098 Add bar
|/
* 625ef71 Add push
* 50bebbc Initial commit
+ : merge base
++ git merge-base origin/master HEAD
+ mb=bbcf4f2e695bf186b7af76f49ec288e068ad804e
+ git diff bbcf4f2e695bf186b7af76f49ec288e068ad804e HEAD --name-only
bar
+ : commits to push
+ git rev-list HEAD --topo-order --reverse --not --remotes=origin
+ xargs git show
commit 90ef098415b3069e676bde710e9885243b02b0bc
Author: Anthony Sottile <asottile@umich.edu>
Date: Mon Nov 12 11:20:31 2018 -0800
Add bar
diff --git a/bar b/bar
new file mode 100644
index 0000000..e69de29
commit aabbc0a9e4f1c3b60b0d93d4fd977efb8f8bf996 (HEAD -> bar)
Merge: 90ef098 bbcf4f2
Author: Anthony Sottile <asottile@umich.edu>
Date: Mon Nov 12 11:20:31 2018 -0800
Merge remote-tracking branch 'origin/master' into bar
+ : source vs origin calculation
++ head -1
++ git rev-list HEAD --topo-order --reverse --not --remotes=origin
+ first_ancestor=90ef098415b3069e676bde710e9885243b02b0bc
++ git rev-parse '90ef098415b3069e676bde710e9885243b02b0bc^'
+ source=625ef7124a9b348855de5c34caa7cbced08cf011
+ git show 625ef7124a9b348855de5c34caa7cbced08cf011
commit 625ef7124a9b348855de5c34caa7cbced08cf011
Author: Anthony Sottile <asottile@umich.edu>
Date: Mon Nov 12 11:20:30 2018 -0800
Add push
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..79a4a6f
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,9 @@
+repos:
+- repo: local
+ hooks:
+ - id: echo
+ name: echo
+ entry: echo
+ verbose: true
+ language: system
+ stages: [push]
+ git diff --name-only 625ef7124a9b348855de5c34caa7cbced08cf011...HEAD
bar
master_only_file
+ git push origin HEAD
echo.....................................................................Passed
hookid: echo
bar master_only_file
Counting objects: 4, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (4/4), 523 bytes | 523.00 KiB/s, done.
Total 4 (delta 1), reused 0 (delta 0)
To /tmp/t/upstream
* [new branch] HEAD -> bar |
If we do this at all, I don't want a configuration value. If you can find a way to improve the push routine or revision differencing to determine this I'd be happiest with that. |
#2424 was marked as duplicate of this, but the workflow I reported there does not involve merges but strictly rebase + force pushes.
Internally I patched pre-commit in our monorepo with this
If current feature branch was updated because of a So it makes no sense for us to run pre-commit for the diff between remote commit vs local commit in this workflow. |
I think https://facebook.github.io/watchman/docs/scm-query.html described this class of diff calculation problem really well. |
solutioning: I do recognize that this problem is workflow specific. So I think a top-level configuration to enable/disable this pre-push strategy, depending on workflow of the repository, would be much appreciated here. |
I would also vote for #2424 to be reopened, since the problems described in these two tickets are related to two different workflows, and the issue with rebase seems more addressable to me at least. The fix suggested by sluongng makes sense to me and I don't think it needs any additional configuration. Contrary to the With the current implementation from I am actually curious if there are any cases at all, where one would prever the original behavior when pushing after rebase. The only downside I see with the change discussed, is that instead of using a |
If I have a feature branch based on some old commit in
develop
ormaster
, and I merge indevelop
ormaster
, the pre-push hooks will run over all the merge commit files. Would it be possible to add a setting to provide a known "good" branch whose changes can be ignored? This is potentially useful as you gradually roll out a new check on a codebase, or if only some people have hooks installed.A current workaround for this is by manually doing something like
git diff $(git merge-base HEAD develop) --name-only [--diff-filter=ACMR?]
in custom hooks, but I'd like to do this for other hooks I haven't written. The effect of this setting would just be to shrink the list of files provided to the hook, so their code wouldn't change.Example repo: https://github.com/prem-nuro/precommit-issue-860
The text was updated successfully, but these errors were encountered: