FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Inconsistent unreleased commit list in next_version() and ReleaseHistory.from_git_history() leading to empty changelog and release · Issue #1252 · python-semantic-release/python-semantic-release · GitHub

Repository navigation

Inconsistent unreleased commit list in next_version() and ReleaseHistory.from_git_history() leading to empty changelog and release #1252

Description

Bug Report

Description

First of all, thank you for a great tool, you did an amazing work!

I have a usual flow with GitHub action that is running after the merge (exactly the one that is described in documentation). And it looks like in case of merge commits it can produce empty release and changelog, but still bump a version.
I have main branchandfeature` branch. The history looks like this

*   v1.2.0 release (main)
*   Merge `feature into `main`
|  \
|   *   Merge 'main' into 'feature' to get latest changes (feature)
| / |
|   |  
*   |    v1.1.0 release (main)
*   |    Some commit in main
|   |
|   *   feat: My new feature (feature)
|  /  
|  

Expected behavior

v1.2.0 release is created, release contains feat: My new feature commit in changelog and release.

Actual behavior

v1.2.0 release is created, but CHANGELOG.md and GitHub release are empty, they don't contain feat: My new feature, just blank

## v1.2.0 (2025-05-23)

Environment

  • Operating System (w/ version): Ubuntu 25.04
  • Python version: 3.10
  • Pip version: 25.1.1
  • Semantic-release version: 9.21.1
  • Build tool (w/ version): None

Configuration

Semantic Release Configuration
[tool.semantic_release]
version_toml = ["pyproject.toml:project.version"]

[tool.semantic_release.changelog]
mode = "update"

Additional context

As I understand, the problem is not in python-semantic-release directly; the problem is the git log output format. Even with topo_order=True here, it still puts my feat: My new feature commit before the v1.1.0 release commit in the history. It looks like after the Merge 'main' into 'feature' to add the latest changes commit, the git log command decided to show commits from main before showing commits from feature.

Why the PR title mentions inconsistency is because in the version resolving logic, the _traverse_graph_for_commits() function returns the correct list of new commits since the last release.
As a result, the version is calculated correctly, but there are no new commits in the release history, so the changelog and release notes are empty.

An obvious idea would be to use _traverse_graph_for_commits()-like logic in ReleaseHistory.from_git_history() to get unreleased commits. But I assume it's not that simple, or it would have been implemented this way already.
I'm happy to provide more info or prepare a PR if you have an idea of how to deal with this behavior.

Activity

  1. added
    bugSomething isn't working properly
    triagewaiting for initial maintainer review
    on May 23, 2025
  2. added
    confirmedPrevent from becoming stale
    and removed
    triagewaiting for initial maintainer review
    on May 23, 2025
  3. codejedi365 commented on May 23, 2025

    Contributor

    @dmitrysleptsov

    First of all, thank you for a great tool, you did an amazing work!

    Thanks, its been a crowd-sourced effort over the years.

    As I understand, the problem is not in python-semantic-release directly; the problem is the git log output format. Even with topo_order=True here, it still puts my feat: My new feature commit before the v1.1.0 release commit in the history. It looks like after the Merge 'main' into 'feature' to add the latest changes commit, the git log command decided to show commits from main before showing commits from feature.

    Why the PR title mentions inconsistency is because in the version resolving logic, the _traverse_graph_for_commits() function returns the correct list of new commits since the last release. As a result, the version is calculated correctly, but there are no new commits in the release history, so the changelog and release notes are empty.

    Thanks for your effort to track down the source of the problem. Your analysis is correct and the git traverse mechanism does a less than desirable job for generating a proper order of commits. I'm glad you like my traverse commits better than git's internal and I'm happy that it actually handles your case automatically.

    An obvious idea would be to use _traverse_graph_for_commits()-like logic in ReleaseHistory.from_git_history() to get unreleased commits. But I assume it's not that simple, or it would have been implemented this way already. I'm happy to provide more info or prepare a PR if you have an idea of how to deal with this behavior.

    It actually is that simple of a solution but not as simple to implement. It was written with duplicate yet separate functionality by the previous maintainers and I have since heavily refactored the version determination algorithm (in v9) for increased performance. At that point, I identified that we were using two different commit tree traversal methods and saw a need to consolidate this code given the costly time behavior. I'm actually surprised you are the first to report an issue like this. I knew about it but no one seemed to have an issue with it (surprisingly) so it wasn't the priority. When I became maintainer, I put a significant amount of effort into increasing the fidelity of all variations of git trees as tests and I did not include a merge from main back into the dev branch so I failed to simulate your situation. The solution I have already been designing will consolidate the traversal code (and hopefully cache it too, across executions) into the ReleaseHistory object but allow for essentially lazy loading of the git tree (so the entire repository doesn't have to be evaluated to determine the next version). Then when the changelog needs to be written (from scratch), then it will parse the repository entirely.

    In the meantime, you could try using git rebase instead as its (IMO) the more modern approach to updating branches for when the trunk has updated. The concept here is that the only thing that is actually "official" is the released code, your branch is not generally released which means the branch owner is responsible for making the changes from the released code. This will also make your git history much cleaner as there is generally only 1 true line of history for a software product.

  4. dzmitrysliaptsou commented on May 23, 2025

    ContributorAuthor

    Thank you for such a quick reply, @codejedi365 !

    I'm actually surprised you are the first to report an issue like this

    Me too, I actually spent some time looking for a similar issue and was surprised when I didn't find any 😄. Maybe this behaviour is not consistent on the git side? I'll try to play around with it a bit more.

    In the meantime, you could try using git rebase instead as its (IMO) the more modern approach to updating branches for when the trunk has updated.

    We're working as a team, so forcing a rebase can start a war between the "merge/rebase" armies. But, as another workaround, I can enforce squashing in the repository and it will help with this as well, as it will create a new commit.

    The solution I have already been designing will consolidate the traversal code (and hopefully cache it too, across executions) into the ReleaseHistory object but allow for essentially lazy loading of the git tree (so the entire repository doesn't have to be evaluated to determine the next version).

    Is there something I can do to help move this forward? I'm happy to help as I really like this tool and just introduced it to the project. And it works flawlessly except for this case.

  5. codejedi365 commented on May 23, 2025

    Contributor

    Me too, I actually spent some time looking for a similar issue and was surprised when I didn't find any 😄. Maybe this behaviour is not consistent on the git side? I'll try to play around with it a bit more.

    I think it is, its just git doesn't quite care to list the individual order of commits, it cares about the combined result of all changes. I've tried multiple command variations to gather a desired order and landed on --topo-order gets the closest.

    We're working as a team, so forcing a rebase can start a war between the "merge/rebase" armies. But, as another workaround, I can enforce squashing in the repository and it will help with this as well, as it will create a new commit.

    Not encouraging a forced rebase, I'm just saying for when this situation occurs. Squashing is a tangental solution but make sure you enable squash commit parsing for PSR otherwise you will likely not see the version & changelog that you desire.

    Is there something I can do to help move this forward? I'm happy to help as I really like this tool and just introduced it to the project. And it works flawlessly except for this case.

    You can always give it a shot to implement the design that I described above. The difficulty will be advanced as these are fundamental functions to the entire project. If you are new to the codebase, I wouldn't feel right recommending it to you (plus I know I will be picky about internals and performance) but I appreciate the willingness. There is also a few open features that will likely conflict with the same files so its not quite the best timing to include a new breaking change release that I'm trying to release today. If anything, towards this issue, you can probably create a replica repo fixture that builds this specific error case. All repo fixtures are found in tests/fixtures/repos/$flow_type/*. Essentially you build a "spec", a list of repository step definitions that replicate the steps to build a repository that would have your git tree above as a session fixture. Then you add function level fixtures to handle the repo caching and commit type specific fixtures. When the function level fixture is called, then it checks if one is already cached and if not it builds a repository based on the defined repository steps. Reference all the other repo fixtures (or walk a debugger on a test case) to see what I mean.

    If you just want to contribute, there are a number of issues open and some identified as "good first issue" if you want to get your feet wet first with those.

  6. dzmitrysliaptsou commented on May 23, 2025

    ContributorAuthor

    If anything, towards this issue, you can probably create a replica repo fixture that builds this specific error case. All repo fixtures are found in tests/fixtures/repos/$flow_type/*

    You mean creating a test fixture to save you some time during implementation, so you already have this test case? I can do that

    If you just want to contribute, there are a number of issues open and some identified as "good first issue" if you want to get your feet wet first with those.

    I see no problems with that, will look into it after this fixture setup

  7. codejedi365 commented on May 23, 2025

    Contributor

    You mean creating a test fixture to save you some time during implementation, so you already have this test case? I can do that

    Yes, that's correct. I don't have one for a trunk merge into a branch for update after a release on main. The closest might be the GitHub Flow ones. But it also applies to the original Git Flow ones too just more complicated.

    You can also add a repo "rebuild" test which essentially runs through the repo definition that you are creating in the fixture and replaces the simulated release/changelog step with PSR's version command. This ensures that PSR will interpret every version of the repository correctly given the configuration and the previous commits. These tests are found under tests/e2e/cmd_version/bump_version/$flow_type and is practically a copy and paste test as I have abstracted most of the functionality. Essentially the difference is the name of the repo it focuses on. If you did the repo definition correctly, then PSR will fail that test case because of your edge case described above (released trunk merged into previously written branch & changelog's do not match expected result).

  8. dzmitrysliaptsou commented on May 31, 2025

    ContributorAuthor

    @codejedi365 , I prepared a PR with the fixture #1268

  9. github-actions commented on Aug 30, 2025

    It has been 90 days since the last update on this confirmed issue. @python-semantic-release/team can you provide an update on the status of this issue?

  10. codejedi365 commented on Sep 13, 2025

    Contributor

    Still under development hopefully in the next few months.

  11. github-actions commented on Dec 13, 2025

    It has been 90 days since the last update on this confirmed issue. @python-semantic-release/team can you provide an update on the status of this issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working properlyconfirmedPrevent from becoming staleneeds-updateNeeds status update from maintainers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL