Repository: nf-core/tools

Issue:
init.defaultBranch=dev is not compatible with nf_core.create.git_init_pipeline
*NOTE* Updated report after diagnosis (see comment thread), original report appended to this description.

### Description of the bug

Running `nf-core lint` or `nf-core create` (v2.5.dev0) when git's `init.defaultBranch` is set to `dev` will exit with a `GitCommandError` traceback.

### Command used and terminal output

(Remember to change your `git config` back, or do this in a VM!)

* git config --global init.defaultBranch dev
* Execute `nf-core create` (or `nf-core lint` in an existing workflow)

```console
GitCommandError: Cmd('git') failed due to: exit code(128)
  cmdline: git branch dev
  stderr: 'fatal: A branch named 'dev' already exists.'
```

### System information

nf-core, version 2.5.dev0 (aff328648d8519e085a975767ebc865868256e09)

---

### Description of the bug

Running `nf-core lint` (v2.5.dev0) on a workflow inside a git repository with an existing `dev` branch yields a `GitCommandError`. It appears the `file_unchanged` lint step leads to the attempted creation of a branch (see traceback below).



### Command used and terminal output

* Clone a workflow that has an existing `dev` branch (or create one)
* Execute `nf-core lint`

```console
GitCommandError: Cmd('git') failed due to: exit code(128)
  cmdline: git branch dev
  stderr: 'fatal: A branch named 'dev' already exists.'
```

Is it expected that the `file_unchanged` lint step leads to the attempted creation of a branch? See:

https://github.com/nf-core/tools/blob/cc1ab618692d14c2203311009a21a187c92c47ef/nf_core/lint/files_unchanged.py#L135-L138

https://github.com/nf-core/tools/blob/cc1ab618692d14c2203311009a21a187c92c47ef/nf_core/create.py#L500

I'm wondering if the `CreatePipeline` call should be passing `no_git=True`?

### System information

nf-core, version 2.5.dev0 (cc1ab618692d14c2203311009a21a187c92c47ef)


Discussion:
Hi @SamStudio8, I am not able to reproduce this error, could you provide an example of the workflow that generated it? Thank you!
Hi @mirpedrol , thanks for taking a look. My steps to reproduce this below:

```
python -m virtualenv ~/venv/nfcore-1688
source ~/venv/nfcore-1688/bin/activate
python -m pip install git+https://github.com/nf-core/tools.git@cc1ab618692d14c2203311009a21a187c92c47ef
mkdir nfcore-1688
cd nfcore-1688
git clone git@github.com:nf-core/sarek.git
cd sarek
nf-core lint
```
Update: I'm able to reproduce this from today's dev HEAD at `aff328648d8519e085a975767ebc865868256e09`.
I'm sorry but still can't reproduce, I get other linting errors but the command runs fine.
```
│ files_unchanged: .github/PULL_REQUEST_TEMPLATE.md does not match the template                     │
│ files_unchanged: .github/workflows/linting.yml does not match the template                        │
│ files_unchanged: assets/email_template.txt does not match the template                            │
│ actions_ci: '.github/workflows/ci.yml' does not check minimum NF version  
```

I am wondering if it's related to the installation? I am using these versions:
Python 3.9.7
pip 22.2
nf-core/tools version 2.5.dev0
Nextflow version 21.10.6 build 5660
@mirpedrol Thanks for trying that out once more! As you were unable to reproduce my error, I tried another machine and found the command does indeed work fine as you had demonstrated. As I could still reliably reproduce the error on the first machine, I followed each step of the traceback to try and determine what was happening. I confirmed that as part of linting for `files_changed`, a temporary repository is created in a temporary directory, and this routine is only performed once. All good so far.

Upon inspecting the temporary directory itself, I see that the repository has been created, and has two branches: `TEMPLATE` and `dev`. But, how can there be a `dev` branch before the call to `repo.git.branch("dev")` succeeds you ask? Yes, it's my `~/.gitconfig`!

```
[init]
    defaultBranch = dev
```

I've updated the title of this issue to correctly identify the real problem: "init.defaultBranch=dev is not compatible with nf_core.create.git_init_pipeline". Indeed, any part of `nf-core` that uses `git_init_pipeline` including the `nf-core create` command will fail with the `GitCommandError` I opened this issue with, when the default branch is set to `dev`.

I'm not sure to what degree `nf-core` should worry about this particular edge case (ie. it might be out of scope to change the `dev` branch to a temporary name, or try and change the `defaultBranch` entirely), but it is always nice to seal up cases that blow up with an unhelpful traceback with a nice error instead. I note it is straightforward to use `gitpython` to find the `defaultBranch` (example below). Perhaps `nf-core` could at least catch the case where the user's default branch is `dev`, cowardly refuse to run commands and exit with a better warning?

```
>>> git.config.GitConfigParser().get_value("init", "defaultBranch")
'dev'
```

Thanks for your patience on this one!
> Perhaps nf-core could at least catch the case where the user's default branch is dev, cowardly refuse to run commands and exit with a better warning?

Thanks @SamStudio8 ! This is a good idea. Especially, given how long it has taken to finally figure this out. Be nice to catch this properly.

`dev` is a pretty common name for a branch, particularly for anyone following a git-flow style development process. For temporary branches a name that's unlikely to clash with any existing branch should be used. Here's some random data to get you started: `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` 😄 
> `dev` is a pretty common name for a branch, particularly for anyone following a git-flow style development process. For temporary branches a name that's unlikely to clash with any existing branch should be used. Here's some random data to get you started: `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855` 😄

Sorry @cjw85 I have some files using that data already.
Yeah me too 👀 
> `dev` is a pretty common name for a branch, particularly for anyone following a git-flow style development process.

@cjw85 yes, but `nf-core create` is creating a brand new git repo from scratch. So unless you have `init.defaultBranch` in your git config it's basically impossible to have a conflict with the branch name.

This is the first time this has come up in ~4 years and 100s of people running the command, so it's fairly far out in edge-case territory 😅 (kudos! 🙇🏻 )
I believe Sam is suggesting that `nf-core lint` has this issue independent of `nf-core create`.
Yup and I think it should at least fail gracefully in both cases 🙂 Just saying that I don't think that we need to change any behaviour. Not sure why `lint` would be failing with this 🤔 I'd be curious to see where that's coming from.

Resolving patch:
diff --git a/nf_core/create.py b/nf_core/create.py
--- a/nf_core/create.py
+++ b/nf_core/create.py
@@ -2,6 +2,7 @@
 """Creates a nf-core pipeline matching the current
 organization's specification based on a template.
 """
+import configparser
 import imghdr
 import logging
 import os
@@ -490,7 +491,24 @@ def download_pipeline_logo(self, url, img_fn):
             break
 
     def git_init_pipeline(self):
-        """Initialises the new pipeline as a Git repository and submits first commit."""
+        """Initialises the new pipeline as a Git repository and submits first commit.
+
+        Raises:
+            UserWarning: if Git default branch is set to 'dev' or 'TEMPLATE'.
+        """
+        # Check that the default branch is not dev
+        try:
+            default_branch = git.config.GitConfigParser().get_value("init", "defaultBranch")
+        except configparser.Error:
+            default_branch = None
+            log.debug("Could not read init.defaultBranch")
+        if default_branch == "dev" or default_branch == "TEMPLATE":
+            raise UserWarning(
+                f"Your Git defaultBranch is set to '{default_branch}', which is incompatible with nf-core.\n"
+                "This can be modified with the command [white on grey23] git config --global init.defaultBranch <NAME> [/]\n"
+                "Pipeline git repository is not initialised."
+            )
+        # Initialise pipeline
         log.info("Initialising pipeline git repository")
         repo = git.Repo.init(self.outdir)
         repo.git.add(A=True)


Test patch: