4

Suppose I have the following manifest file for the repo tool (MCVE script is included at the end of this post):

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote name="repo1" fetch="/tmp/standalone_repo_expt/git.repos" />
  <remote name="repo2" fetch="/tmp/standalone_repo_expt/git.repos" />
  <default remote="repo1" revision="master" />
  <project name="repo1" path="repo1" />
  <project name="repo2" path="repo2"  />
</manifest>

I'm able to run repo init ... followed by repo sync into a brand new directory (i.e., without any prior contents). But when I cd into the resulting repo1 subdirectory (e.g., /tmp/standalone_repo_expt/work_area/myproject/repo1/), and do a git status I see this:

$ git status
Not currently on any branch.
nothing to commit, working tree clean

And then showing what branches are available I see:

$ git branch -a
* (no branch)
  remotes/m/master -> repo1/master
  remotes/repo1/master

Why did repo sync not check out to the default branch (master) that I had specified in the default tag in the manifest file?

Similar questions

This is similar to Why doesn't git repo checkout the branch specified? but is not quite the same issue. My issue is that no branch is checked out, and that seems wrong. I should not have to do anything else other than the repo sync, and I should not have to run git checkout master in all of the repositories managed by that manifest file.

This also seems similar to https://stackoverflow.com/a/66264612/257924 but using repo init -b master does not do what I want either (has no effect on this problem of the repositories not being checked out to the specified branch).

https://stackoverflow.com/a/16917618/257924 gets close to answering this question, but does not explain why git branch -a does not contain the master branch right after the repo sync.

Repo tool version

The repo tool was pulled from source directly on 2021-11-15 via:

curl https://storage.googleapis.com/git-repo-downloads/repo > /tmp/standalone_repo_expt/bin/repo

and the PATH set to include /tmp/standalone_repo_expt/bin.

MCVE script

#!/bin/bash

function generate_repo {
  local repo_num="$1"
  mkdir -p /tmp/standalone_repo_expt/git.repos/repo$repo_num.git
  cd /tmp/standalone_repo_expt/git.repos/repo$repo_num.git
  git init --bare

  mkdir -p /tmp/standalone_repo_expt/work_area
  git clone /tmp/standalone_repo_expt/git.repos/repo$repo_num.git || {
    echo ERROR: git clone /tmp/standalone_repo_expt/git.repos/repo$repo_num.git
    exit 1
  }

  (
    cd repo$repo_num
    touch repo$repo_num.README
    git add repo$repo_num.README
    git commit -m "Add repo$repo_num.README"
    git push origin
  )

  (
    mkdir -p /tmp/standalone_repo_expt/work_area/repo$repo_num.test_clone
    cd /tmp/standalone_repo_expt/work_area/repo$repo_num.test_clone
    git clone /tmp/standalone_repo_expt/git.repos/repo$repo_num.git
    ls -ld repo$repo_num/*
    cd repo$repo_num
    git status
  )
}

# Remove the entire set of git repos for reproducable execution:
rm -rf /tmp/standalone_repo_expt

# Generate the git repositories, that we wish to combine into one
# larger directory, using the repo tool:
generate_repo 1
generate_repo 2

# Install the repo tool from source, not using any package managers:
mkdir -p /tmp/standalone_repo_expt/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > /tmp/standalone_repo_expt/bin/repo 
test -s /tmp/standalone_repo_expt/bin/repo || {
  echo "ERROR: Failed to download repo tool into /tmp/standalone_repo_expt/bin/repo"
  exit 1
}
chmod a+rx /tmp/standalone_repo_expt/bin/repo
PATH="/tmp/standalone_repo_expt/bin:${PATH}"
which repo >& /dev/null || {
  echo "ASSERTION FAILED: Failed to install the repo tool."
  exit 1
}

# Create the git repository that houses the manifest that are needed
# by the repo tool that reference the git repositories generated
# above:
mkdir -p /tmp/standalone_repo_expt/git.repos/manifests.git
cd /tmp/standalone_repo_expt/git.repos/manifests.git
git init --bare

# Clone the manifest bare repo so we can add the manifest file, and
# push it back:
cd /tmp/standalone_repo_expt/work_area
git clone /tmp/standalone_repo_expt/git.repos/manifests.git || {
  echo ERROR: git clone /tmp/standalone_repo_expt/git.repos/manifests.git failed
  exit 1
}
cd manifests
cat > default.xml <<EOF.manifest
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <remote name="repo1" fetch="/tmp/standalone_repo_expt/git.repos" />
  <remote name="repo2" fetch="/tmp/standalone_repo_expt/git.repos" />
  <default remote="repo1" revision="master" />
  <project name="repo1" path="repo1" />
  <project name="repo2" path="repo2"  />
</manifest>
EOF.manifest

cat default.xml

git add default.xml
git commit -m "Manifest file used by the repo tool"
git push origin || {
  echo ERROR: git push origin failed
  exit 1
}

set -x
mkdir -p /tmp/standalone_repo_expt/work_area/myproject
cd /tmp/standalone_repo_expt/work_area/myproject
repo init /tmp/standalone_repo_expt/git.repos/manifests.git
repo sync

cd repo1
pwd
ls -l
git status
bgoodr
  • 2,744
  • 1
  • 30
  • 51
  • I have no idea *why* Repo did what it did, but the answer for [tag:git] is "just go check out master directly". Obviously this isn't the answer you want. (Perhaps you want to drop the [tag:git] tag.) – torek Nov 15 '21 at 21:21
  • `repo sync` is designed to checkout a detached HEAD. I thinks it's because a revision specified in the manifest is not always the current head of a branch. It could be an old commit of a branch, or just a tag, or just a random commit of a ref. To sync the code exactly the same with the revisions specified in the manifest, I suggest you use `repo sync -d` so that even if the existing repository has checked out a branch, it always goes back to the specified revision as a detached HEAD. You could find more in repo's source code, mainly in `.repo/repo/subcmds/sync.py` and `.repo/repo/project.py`. – ElpieKay Nov 16 '21 at 09:48
  • 1
    As to `repo init -b master`, the master means the master branch of the repository that holds the manifests. The manifest repository is specified by `-u `. – ElpieKay Nov 16 '21 at 09:53
  • 1
    @ElpieKay ok, well, then I really don't see the utility of this repo tool. It would rather make more sense for `repo sync` to check out the branch that I have specified in the `revision` attributes, versus leaving all of the repositories in a detached HEAD, forcing me to explicitly execute `git checkout ` in each repository. – bgoodr Nov 18 '21 at 06:14
  • 1
    @bgoodr Consider the manifest as a `tag` for a number of repositories. It takes the snapshot of all the involved repositories. If all the repositories have the same branch name, you could use `repo start --all ` to checkout the branch. If they don't, you could use `repo forall` with `-r ` or `-g ` to execute `git checkout ` in specified repositories. If you take part in AOSP development, I think you would find its utility. – ElpieKay Nov 18 '21 at 06:33
  • @ElpieKay Thank you. That's is helpful, since it revealed the very bug in the [repo start docs](https://source.android.com/setup/develop/repo#start) that led me astray, and I quote: "Begins a new branch for development, starting from the revision specified in the manifest." which is wrong because `repo start` requires the user to specify a `` on the command line, and does not do a `git checkout` "from the revision specified in the manifest". If it did the latter, then it should run `git checkout ` where `` _could_ be different on each repository being checked out. – bgoodr Nov 20 '21 at 18:39
  • @ElpieKay But, having said the last sentence above where the `` _could_ be different, etc., perhaps that is your point with "take part in AOSP" development, which is not my end-goal here, in that that is the way AOSP development works somehow. So, is there something specifically wrong about having `repo start` checkout the branches specified in the manifest, versus requiring the user to somehow just know which branch they need for _all_ repos? – bgoodr Nov 20 '21 at 18:42
  • What does "MSE" stand for? – Michael Burr May 01 '22 at 08:19
  • @MichaelBurr You got me on that one. It means MCVE: https://stackoverflow.com/help/minimal-reproducible-example so I edited that in. Good catch. – bgoodr May 07 '22 at 22:04

1 Answers1

1

repo doesn't create a local branch for you. When you check out a remote branch you'll end up with a detached head (since you can't make commits on the remote branch anyway).

https://groups.google.com/g/repo-discuss/c/yPoPazTRgMA

Peter Silon
  • 457
  • 2
  • 11
  • Yes, this was discovered and referred to in the comments of my original post. At least for now I've given up on using this tool, because it does not do what I wanted to do, and the amount of work I will have to invest in it to force it to do my bidding is excessive in my use cases. – bgoodr May 09 '22 at 04:29