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

Clarify Capstone branching strategy #1781

Open
2 of 3 tasks
tmfink opened this issue Aug 29, 2021 · 23 comments
Open
2 of 3 tasks

Clarify Capstone branching strategy #1781

tmfink opened this issue Aug 29, 2021 · 23 comments

Comments

@tmfink
Copy link
Contributor

tmfink commented Aug 29, 2021

Historically, this project has used the active branches:

  • Past version branches (v2, v3, v4)
  • next: what will be the next release

The master branch is not really used, but is still the default HEAD branch. This confuses contributors.

As of writing:

I propose the following branching strategy of the project

  • Document branching strategy
  • Update repository HEAD (default) branch (if needed)
  • Deprecate any branches (if needed)
    • We can do a final commit to the README in that branch that describes the branch as deprecated
    • We can also lock the branch
@tmfink
Copy link
Contributor Author

tmfink commented Aug 29, 2021

My proposed branching strategy is to "support" branches:

  • next: contains all active development/new features
  • old version "vN" branches (v2, v3, ...)
  • deprecate master branch

Guidelines:

  1. All new features commits go into the next branch
  2. Bugs should be fixed in the "newest" branch branch first
    • As applicable, cherry-pick/merge bug fixes back to "vN" if they are still supported
  3. When we create a new major release of capstone, create the new "vN" from the next branch

@keenk
Copy link
Contributor

keenk commented Sep 7, 2021

I have to agree that the names are confusing for developers new to Capstone. There have been so many issues opened where the solution was basically "use the next branch".

It makes sense to have an experimental / unstable / next - type branch when there is a high rate of commits. But the rate of commits here seems pretty slow. I think it would be less confusing for new people if next (or whatever it comes to be called) became the primary branch.

@tmfink
Copy link
Contributor Author

tmfink commented Nov 11, 2021

@aquynh could you change the default branch to next? I see several PRs were mistakenly opened against master.

https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-branches-in-your-repository/changing-the-default-branch

@aquynh
Copy link
Collaborator

aquynh commented Nov 11, 2021 via email

@XVilka
Copy link
Contributor

XVilka commented May 4, 2023

@aquynh @kabeor since master is deprecated for a long time, and a lot of activity happened in next since, do you think it makes sense to make it default now?

@aquynh
Copy link
Collaborator

aquynh commented May 4, 2023 via email

@XVilka
Copy link
Contributor

XVilka commented May 4, 2023

@aquynh another option would be to let master be, but to make a new branch - main, as the default branch name for Git and GitHub these days, and base it on the latest next. Then, main would represent a "stable" branch, which would allow picking up small patches for making patch releases, while keeping next the default branch. It's also possible to make next default branch on the GitHub in this strategy, but base releases on main, merging next into main when you think it's ready for the next release. How does it sound?

This way it would guarantee not to break anything that relied on master for one reason or another.

@aquynh
Copy link
Collaborator

aquynh commented May 4, 2023 via email

@aquynh
Copy link
Collaborator

aquynh commented May 4, 2023

please see #2011

we have the main branch as the default branch now.

@tmfink
Copy link
Contributor Author

tmfink commented May 4, 2023

(Response added here instead of #2011 so I can quote @XVilka comment)

@aquynh another option would be to let master be, but to make a new branch - main, as the default branch name for Git and GitHub these days, and base it on the latest next. Then, main would represent a "stable" branch, which would allow picking up small patches for making patch releases, while keeping next the default branch. It's also possible to make next default branch on the GitHub in this strategy, but base releases on main, merging next into main when you think it's ready for the next release. How does it sound?

This way it would guarantee not to break anything that relied on master for one reason or another.

I don't think we want to do this since there would be no good way to update the main (latest stable) branch from next.
The next branch is supposed to be the "next" version, so we would want the next branch history to just become the next main branch.

Our options would be:

  1. Do hard reset of stable to next when we pull a create a new major version.
    • This would regularly break everyone's Git checkouts and make it much more difficult to work with the project.
  2. Merge next into stable
    • This would cause crazy conflicts and we would just want to take everything from the next branch anyway.

Also, we want next to be the default branch because that's where "new development" should go.
Only bug fixes should go into any "stable" branch. Also, bugs should be fixed in the forward development branch (AKA next) first. If necessary, bug fixes can be cherry-picked to an older branch.

Proposal

  • Stable versions have a branch name that indicates the version (like we have been doing)
  • Deprecate master and main
    • Delete main since it's so new and almost nobody will have checked it out
    • Rename master to master_old. Github automatically redirects URLs when we rename the branch. Causing breakage for this case would not be bad since this branch is long since deprecated.
  • Make next the default branch (repo HEAD)

Example

If the latest "stable" version is "6.X.X", then we would have branches:

  • next
    • Default HEAD branch; commits go here by default
    • New features for future major version "7.X.X" will go here
  • v6, v5, ...
    • Bug fixes for "stable" releases go here

When we release a new major version, such as "7.X.X", we would only need pull a new branch v7 from next.

To fix a bug in any version "train", we simply need to commit to the branch for the corresponding version.

I would be happy to document this process in a wiki page.

@aquynh
Copy link
Collaborator

aquynh commented May 4, 2023

the main branch is only updated when we release the new versions, and at that time we merge next to main, like we always did with the master branch before.

the reason I made master deprecated is because there were some mistakes so it is impossible to merge next to it without a lot of nasty fixes.

sorry that i don't get what you mean: what is wrong with the above plan?

@tmfink
Copy link
Contributor Author

tmfink commented May 5, 2023

Sorry for not being clear. 😄

the main branch is only updated when we release the new versions, and at that time we merge next to main, like we always did with the master branch before.

Would you only update main when releasing an new major version, or also for minor/patch versions?
For example, would you update main when incrementing major version going from version "5.99.99" to version "6.0.0"?
Would you update main when incrementing a patch version from version "6.0.0" to version "6.0.1"?

If you only update main for major versions, then main would always be very out of date compared to the version branch (like v6).

If you update main for every new release (including minor/patch versions), then when you jump major versions, the merge won't be clean. You will get a lot of conflicts because the code for "5.99.99" will be much different than the code for next that will correspond to "6.0.0". A git merge is meant to merge separate threads of development, but main would not be a thread of development--it would effectively be a pointer that gets updated.

Git branches exist so you can commit into them. It sounds like you will never commit directly into main but only do a fast-forward merge OR a git reset --hard.

It sounds like you want a "read only branch". Instead of using a branch, you could just create a "latest-stable" tag that you update on every release. For example, the neovim repo has a stable tag that gets updated for every release.

If you want folks to be able to easily determine the latest release but avoid committing to a main branch, then I recommend adding a stable tag. I think "stable" or "latest-stable" is a more descriptive name than "main" for the tag.

@XVilka
Copy link
Contributor

XVilka commented May 5, 2023

@tmfink you can avoid conflicts during the merge using:

# when we are on the "next" branch
git checkout -b main-merge
git merge main -s ours
git checkout main
git merge main-merge --no-ff -m "Merge 'next' branch into 'main'"

@tmfink
Copy link
Contributor Author

tmfink commented May 7, 2023

@tmfink you can avoid conflicts during the merge using:

@XVilka Yes, we could use the "ours" merge strategy to effectively ignore all changes that went into the latest stable release branch (e.g. v6) after it was pulled from the next branch. But, I don't see the benefit and think it would lead to contributor confusion.

Why main branch would confuse first-time contributors

The main branch (AKA "latest stable") would not be an active "thread of development". However, the most frequently followed convention is to have branches with names such as main be the "forward development branch".

Even if we lock the main branch using GitHub settings to disallow pull requests, many contributors will end up pulling a branch from main to do work. Then, they'll try to make a pull request from their branch to main but be prevented (by GitHub). They will then be confused why it does not work and need to learn how Capstone's branching strategy deviates from the norm.

In this case, the contributor will need to rebase their changes to the next branch. The rebase might have conflicts and thus the contributor may have wasted effort, but the biggest issue is that rebasing is a somewhat advanced topic and not a simple task for many users. This will sometimes require back and forth in discussions in the PR thread explaining how to git rebase (or equivalent) and make a new PR.

Even if the contributor wants to commit a bug fix to both next and the latest stable branch, bug fixes should go into next branch first ("always fix forward first").

How "ours" merge strategy makes history more confusing

Looking at git log main or the output of commands like git branch --contains 12345 could lead to the false conclusion that the main branch has a commit that it does not actually have since commits that went into "stable" branches (v5, v6, ...) would exist in the history but would have been discarded once the latest next branch is merged in.

Summary

In summary, I think we want to avoid violating the principle of least astonishment to save the time of both first-time contributors (doing wasted work) and long-time contributors (having to explain "please make a new PR").

We should delete/deprecate/lock the master/main branches and only use the next and "stable version branches" (v1, v2, v3, ...).

@tmfink
Copy link
Contributor Author

tmfink commented May 7, 2023

@XVilka I think both of those strategies would be more complicated and require more work for all contributors than what I have described above.

@aquynh another option would be to let master be, but to make a new branch - main, as the default branch name for Git and GitHub these days, and base it on the latest next. Then, main would represent a "stable" branch, which would allow picking up small patches for making patch releases, while keeping next the default branch.

We need to have separate branches for each "release train" ("2.X", "3.X", ...). In fact, we already have branches v2, v3, ... for this exact purpose. It would be confusing and error prone to "juggle" maintaining the latest release branch (e.g. v4) and a new branch main. Both branches would need to have identical state--it makes to keep a main branch`.

It's also possible to make next default branch on the GitHub in this strategy, but base releases on main, merging next into main when you think it's ready for the next release. How does it sound?

Per my previous point, there's no benefit to having a main branch when we have a next branch and v* branches already.

Basically, my recommendation (since we have been doing it this way for years) is to have our next branch be our forward development branch (most projects use a main or master branch for this purpose). The only other branches we need are for stable v* version branches (v2, v3, v4, ...) that get pulled from next when we are getting ready for that release train.

Adding an additional main branch has no benefit. If we want users to be able to see what the latest stable release is, we can just have a Git tag called latest-stable that we update on every release like the Neovim project does as I described in the above comment.

@XVilka
Copy link
Contributor

XVilka commented May 7, 2023

@tmfink for me it sounds like a viable strategy too, let's see what @aquynh and @kabeor think.

@aquynh
Copy link
Collaborator

aquynh commented May 7, 2023 via email

@tmfink
Copy link
Contributor Author

tmfink commented May 7, 2023 via email

@XVilka
Copy link
Contributor

XVilka commented May 8, 2023

I also agree that would work for us with the auto-sync effort perfectly. 👍

@aquynh
Copy link
Collaborator

aquynh commented May 8, 2023

ok i made the changes:

  • v5 is for stable release of version 5.
  • next becomes the default branch
  • main is removed

@XVilka
Copy link
Contributor

XVilka commented May 8, 2023

Then it makes sense to close this one maybe?

@tmfink
Copy link
Contributor Author

tmfink commented May 8, 2023

I like all of the changes.

I would say the only thing left is to:

  • lock the master branch (I can't do that)
  • add a wiki page documenting the branching (I can handle that)

@tmfink
Copy link
Contributor Author

tmfink commented May 8, 2023

I created a wiki page describing the branching model.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants