Skip to content
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

Git repository gets messed up with git-fetch-with-cli = true #7072

Closed
d-e-s-o opened this issue Jun 26, 2019 · 5 comments · Fixed by #7082
Closed

Git repository gets messed up with git-fetch-with-cli = true #7072

d-e-s-o opened this issue Jun 26, 2019 · 5 comments · Fixed by #7082
Labels
C-bug Category: bug

Comments

@d-e-s-o
Copy link
Contributor

d-e-s-o commented Jun 26, 2019

Problem

Some of my projects are hosted on private repositories, access to which requires SSH. So I have a dependency specification such as:

[dependencies]
a-dep = {git = "ssh://private-host/~/git/a-dep.git"}

private-host here is an SSH alias with public key authentication configured etc. To make this work I need to tell cargo to actually fall back to using git, and not just libgit (or whatever it uses internally; because that doesn't honor ssh aliases). Long story short, I have this setting in my projects:

$ cat .cargo/config
[net]
git-fetch-with-cli = true

Now, given this setup what I have seen plenty of times with different dependencies, is that when I git rebase with something like

git rebase --interactive HEAD~5 --exec 'cargo build'

the project's git repository actually gets messed up. Say I am rebasing master. In some cases master got silently replaced with master from a-dep. The original master is just gone.
I noticed this because git has a safeguard in that it checks that the branch that is currently rebased and that will get replaced after the operation finishes still is at the expected SHA-1. If that is not the case it aborts. Because master now is no longer the proper master but that of a dependency being pulled in, this check obviously fails.

I have also seen unrelated branches that exist in a-dep (to stay with the example) suddenly appear as branches in the repository I am working in itself.

Steps
I don't have a way to reproduce this issue reliably. Every time I hit it was during rebase. I believe to have seen this problem only when the rebase -- recall that I cargo build as part of the rebase -- pulls in a different revision of the dependency, meaning that an actual git fetch is happening.

I am suspecting that is a problem with cargo on the basis that I have never had problems with git itself (I rebase a lot), but I don't know that for a fact.

$ cargo version
cargo 1.35.0
@d-e-s-o d-e-s-o added the C-bug Category: bug label Jun 26, 2019
@alexcrichton
Copy link
Member

Thanks for the report! Can you elaborate on why you think rebasing factors in here and what rebasing is going on? Operations on a local git repository should be pretty separable from operations on a remote git repository. Cargo internally manages this git dependency and doesn't ever do rebases, it just uses the git CLI tool to perform a fetch and then uses libgit2 to actually read the repository.

@d-e-s-o
Copy link
Contributor Author

d-e-s-o commented Jun 26, 2019

I don't know if rebasing actually is a factor. But every time I encountered the issue was during rebasing. Now it's possible it's only detected then (because of the safeguard on the side of git), but I would say that I would eventually have noticed if my master was from a different repository :-)
The truth is, I can't really make sense of much of the problem and I am also struggling to see a connection with cargo. Yet, I've never encountered any of that without cargo involvement. I'll try and reproduce it at some point and upload the setup to the degree that is possible.

@d-e-s-o
Copy link
Contributor Author

d-e-s-o commented Jun 29, 2019

Okay, so it is actually pretty easy to reproduce. Here is the recipe:
(rpigit is the remote I use, it's an SSH endpoint with public key authentication set up via ~/.ssh/config)

# Create a new bare repository foo.git on `rpigit`.

cargo init --lib foo
cd foo
git commit --allow-empty --message 'Create new repository for foo'
git add .
git commit --message 'Add cargo init created content to foo'
cat <<EOF >> src/lib.rs
pub fn foo() {
    println!("foo!")
}
EOF
git add --update .
git commit --message 'Add foo()'
git remote add -f rpi rpigit:~/git/foo.git
git push rpi

cd ..
cargo init --bin bar
cd bar
git commit --allow-empty --message 'Create new repository for bar'
git add .
git cm 'Add cargo init created content to bar'
cat <<EOF > .cargo/config
[net]
git-fetch-with-cli = true
EOF
git add .cargo/
git commit --message 'Add .cargo'
echo 'foo = {git = "ssh://rpigit/~/git/foo.git"}' >> Cargo.toml
git add --update .
git commit --message 'Depend on foo'
set +H
patch -p1 <<EOF
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,6 @@
+use foo::foo;
+
 fn main() {
     println!("Hello, world!");
+    foo()
 }
EOF
git add --update .
git commit --message 'Use foo'
$ /tmp/bar (master %) $ true; while [ $? -eq 0 ]; do GIT_EDITOR=/bin/true git rebase --interactive HEAD~3 -x 'cargo build'; done
Executing: cargo build
   Compiling bar v0.1.0 (/tmp/bar)
    Finished dev [unoptimized + debuginfo] target(s) in 0.22s
[detached HEAD f51962] Add .cargo
 Date: Sat Jun 29 07:23:43 2019 -0700
 1 file changed, 2 insertions(+)
 create mode 100644 .cargo/config
Executing: cargo build
    Updating git repository `ssh://rpigit/~/git/foo.git`
   Compiling bar v0.1.0 (/tmp/bar)
    Finished dev [unoptimized + debuginfo] target(s) in 0.48s
[detached HEAD 7791f1] Depend on foo
 Date: Sat Jun 29 07:16:09 2019 -0700
 1 file changed, 1 insertion(+)
Executing: cargo build
   Compiling bar v0.1.0 (/tmp/bar)
    Finished dev [unoptimized + debuginfo] target(s) in 0.22s
[detached HEAD 003e68] Use foo
 Date: Sat Jun 29 07:45:01 2019 -0700
 1 file changed, 3 insertions(+)
error: update_ref failed for ref 'refs/heads/master': cannot lock ref 'refs/heads/master': is at a9eeabc42373e48bf5f64e367df26757aea3c756 but expected 82115cecfab4af690662e8f8c719ccc6b45e0150
error: could not update refs/heads/master

Look what has become of master:

$ /tmp/bar (master %|REBASE-i 6/6) $ git log master
commit a9eeabc42373e48bf5f64e367df26757aea3c756 (master)
Author: Daniel Mueller <deso@posteo.net>
Date:   Sat Jun 29 07:20:57 2019 -0700

    Add foo()

commit 8059fe629490c3e378f30463ba2729fe1f4f2cb6
Author: Daniel Mueller <deso@posteo.net>
Date:   Sat Jun 29 07:06:10 2019 -0700

    Add cargo init created content to foo

commit 0e23af1732a0c6dab45192ad82160548db2d2289
Author: Daniel Mueller <deso@posteo.net>
Date:   Sat Jun 29 07:05:04 2019 -0700

    Create new repository for foo

(it is possible that no SSH remote is needed; perhaps it can be reproduced with a local path to foo; I did only do so much experimentation and what I described resembles what I did to hit the issue to begin with)

@ehuss
Copy link
Contributor

ehuss commented Jun 29, 2019

That's an odd one! I see the problem, at least for your repro. git sets the environment variable GIT_DIR when run by rebase, which causes the git fetch to run in the wrong directory. I have posted #7082 with a fix.

@d-e-s-o
Copy link
Contributor Author

d-e-s-o commented Jun 29, 2019

Very nice! Thanks! I guess that then also explains why I don't see it consistently and, as I suspected, only when an actual fetch is performed.

bors added a commit that referenced this issue Jun 29, 2019
Clean environment when git-fetch-with-cli is used.

When the GIT_DIR environment variable is set, git-the-cli will use that instead of looking at cwd.  This can happen, for example, when using the `exec` command in `git rebase` to call cargo.  This causes cargo to fetch into the wrong directory.

Closes #7072
d-e-s-o added a commit to d-e-s-o/portage-overlay that referenced this issue Jun 30, 2019
This change adds a patch for a fix in cargo that causes the branches in
a git repository for a cargo managed project to potentially be messed up
during a rebase --exec cycle when a git fetch is invoked as part of the
command being executed.
This problem is tracked upstream as issue #7072 [1].

[1] rust-lang/cargo#7072
d-e-s-o added a commit to d-e-s-o/portage-overlay that referenced this issue Jul 9, 2019
This change adds a patch for a fix in cargo that causes the branches in
a git repository for a cargo managed project to potentially be messed up
during a rebase --exec cycle when a git fetch is invoked as part of the
command being executed.
This problem is tracked upstream as issue #7072 [1].

[1] rust-lang/cargo#7072
d-e-s-o added a commit to d-e-s-o/portage-overlay that referenced this issue Jun 4, 2020
This change adds a patch for a fix in cargo that causes the branches in
a git repository for a cargo managed project to potentially be messed up
during a rebase --exec cycle when a git fetch is invoked as part of the
command being executed.
This problem is tracked upstream as issue #7072 [1].

[1] rust-lang/cargo#7072
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants