I have a git question. I like using a development branch that tracks all commits individually, then I squash merge into master, then tags and CI and all happen on master. So this is basically the flow

git switch master

git merge --squash develop

git commit

git switch develop

git merge master

My issue is that the compare history does not collapse after merging master into develop. I don't want to lose the history of develop but I want git to ignore the branch history before the merge if that makes sense?

Reply to this note

Please Login to reply.

Discussion

Sorry no, that doesn't make sense. As soon as you squash commits, you have a different hash and the history diverges from here. That holds true, even if the actual file content is the same.

Yeah that explains it thank you. So is there any way to acheive this while also having the squash feature, effectively 2 linear branches?

No

Try this instead: git rebase -i origin/master. Pick and squash manually. This way you can squash all "cleanup" commits, rewrite some commit messages and deliver a much cleaner PR to master branch. Giant commits with tons of code are meaningless anyway, since you can't read what happened. Managing a clear and understandable git history takes a lot of discipline.

Three options:

1. No merge - squash the commits in the branch, rebase onto master, set the tip of master to that commit. History is lost.

2. Merge - don't squash. Merge into master. The CI should just run on the merge commit. This will keep the useful history for future reference for everyone.

3. Add directly onto master - rebase on master, reset master tip to the tip of your develop branch.

If you go for option one you could keep a local branch that hasn't been squashed for your own person reference.

Ideally all commits in master are always release ready, as in tested and safe to run

I never want anyone to checkout a commit from master and it not compile or pass tests etc

I want individual commits to always happen in the development branch, including feature merges and so on

I only want the history of develop referenced in master (hence the squash)

I want develop to contain the full history of individual commits

I think it's useful information to see what commits from develop make up the latest changes in master if that makes sense.

So master is the short history, and develop is the long detailed history?

If I went with 3 wouldn't that reset the development branch?

Long story short, I built my own CI system (vnbuild) so it's always agnostic, and any user or developer can run it exactly how I do without needing Docker, GH, Jenkins etc. It can rely on branch history to create CI version numbers for me so I don't have to muddy my history with committing version numbers. If I merge the entire history the CI numbers are not incremental. This is my own fault, but I still like that every master commit is safe enough to have a release.

You want option 2. Consider using multiple feature branches rather than a single develop branch to make it clearer what exactly is being merged. Then you can work on different things in parallel whilst having an easier to read commit history.

The issue with 2 is, the entire history is now just in master, there may be multiple previous commits that will not compile when checked out. Also, the issue where a ci version (using git history) may go from tag v0.1.x-ci0001 to v0.1.x-ci0040 if I merge 40 commits into master. I want the next version to go from 0001 to 0002 with git history alone on master.

Ah, you need to use the `--no-ff` flag like so: `git merge --no-ff `

Ohhhhh yeah forgot about that part. So that will merge all changes using a single commit hash. How does this differ from squash if you have the time to explain?

Both contain the full diff but squash destroys the history completely whereas no-ff includes a reference to it, so it can be optionally stores and downloaded.

Pretty excited to play with this tonight! Thank you for the help sir!

So it looks like a --no-ff is not what I wanted. It stuffed all of the develop branch git history into master which it did NOT want :/ Am I using it wrong?

Features are merged into develop, develop is used as a staging branch. I want to keep full develop history. CI tests are run against develop. Once CI tests pass on develop I want to merge changes only (no history) into master. CI is triggered to publish against master, this is a release. Master is merged back into develop to avoid merge conflicts. All feature branches checkout develop not master.

you cant squash like that, as it cant track the commits. i prefer to generally, work in a branch or fork, and keep rebasing my commits into a clean commit and force push until an upstream is ready to accept the PR. this keeps out conflicts and makes PRs easy, but it ruins others being able to work with your branch (because of the force push).

you might be interested in 'git flow' workflow. i dont like it that much but i also dont tend to have long running feature branches that multiple people commit into.

Hmm, yeah I'd want to avoid the force push as it ruins many of my automations as well.

It's mostly I like the flow of squash (history is ignored and changes are merged) however after enough changes it makes PR comparisons really long which is the issue.

i like rebase w squash too, because i use cmd line git and it makes it easier for me to diff and tidy things up for a PR when i squash it down... its not so bad for automation.. tho the automation has to do a reset of the local copy of the branch /fresh checkout.

For now, I'm solo on most of my projects and I don't usually have long running feature branches either, or at least I try not to.