I use Gitlab for source control. Gitlab recently made the switch to using main
as the default branch for new repositories, as described here, which is fine, and I've adjusted my development environments to match.
I would like to change my existing repositories as well. This tutorial describes a way to do this, but involves multiple manual steps and only works on one repository at a time, not to mention the steps of copying over history. As our code base is comprised of hundreds of repositories, this is just not feasible.
Is there a way to automate this in Gitlab or Gitbash?
CodePudding user response:
This is just a matter of creating a new branch from master called main
, deleting the master branch, and adjusting the default/protected branches rules. These operations can be performed using the GitLab API, which would allow you to script these actions.
Basic steps and API references:
Use the create branch API to create the
main
branch from masterUse the edit project API to set the default branch to
main
use the protect branch API to protect
main
(optionally) use the unprotect branch API to remove protections from master and/or use the delete branch API to remove the master branch.
You must, of course, have sufficient permissions to take all these actions in the project.
Finally, you can also use the list projects API to list all of your projects and loop over the results to apply this to all your projects -- you can write a script like for each project; do steps 1-4
Using the python-gitlab
library, a script like this should be about right to do all those steps:
import gitlab
gl = gitlab.Gitlab("https://gitlab.example.com", private_token="your token")
# add your project IDs here
all_projects = [gl.projects.get(1234), gl.projects.get(4567), ...]
# or list all projects programatically: (careful if using gitlab.com!)
# all_projects = list(gl.projects.list(as_list=False))
def get_or_create_main_branch(project):
try:
b = project.branches.get("main")
print("main branch already exists")
return b
except gitlab.exceptions.GitlabError:
print("Creating main branch from ref:", project.default_branch)
project.branches.create({"branch": "main", "ref": project.default_branch})
print("Creating protection rule for main branch")
# Edit access levels per your needs
project.protectedbranches.create(
{
"name": "main",
"merge_access_level": gitlab.const.DEVELOPER_ACCESS,
"push_access_level": gitlab.const.MAINTAINER_ACCESS,
}
)
return project.branches.get("main")
def fix_project(project):
main_branch = get_or_create_main_branch(project)
print("setting default branch to main...", end="")
old_default_branch = project.branches.get(project.default_branch)
project.default_branch = "main"
project.save()
print("Done!")
print("deleting original default branch", old_default_branch.name, "...", end="")
old_default_branch.delete()
print("done!")
for project in all_projects:
print("-" * 20)
print("Checking", project.path_with_namespace, "for default branch")
if project.default_branch != "main":
print(
f'Default branch is "{project.default_branch}", not "main". Attempting Fix...'
)
try:
fix_project(project)
except gitlab.exceptions.GitlabError as e:
# sometimes bare repos without any commits will error out
print("FATAL. Failure getting or creating main branch", e)
print("Skipping")
continue # move on to next project in the loop
print("successfully fixed", project.path_with_namespace)
else:
print('Default branch is already "main", skipping')
continue