Do squashed pull requests show up in the contributions graph as a single commit? - github

I'm working on feature branches that can have over a hundred commits over the course of a week or two. I've expected to get daily marks on my contribution graph for these daily commits once my pull request is accepted, but when that pull request gets "Squashed and merged", it looks like it just shows up as a single commit on the contribution graph.
Is this the intended behavior, or are my commits missing for a different reason?

Yes, this is the intended behavior. You only got one commit merged. That's the point of squash and merge.
I do not recommend squash merges. It takes all the carefully considered commit history about how the branch was developed and mashes it into a convenient but homogeneous paste.
I'm working on feature branches that can have over a hundred commits over the course of a week or two.
I would say this is the real problem. Feature branches should not regularly have over a hundred commits. Your features are too
big, or you're making a lot of commits to fix previous commits, or you have a lot of incidental merge commits from updating your branch, or all of the above.
Update your branch using rebase instead of merge. git rebase main rewrites your branch as if it were written on top of the latest version of main all along. This removes merge commits which say nothing but "I updated my branch" and makes it easier to see what work has been done on the branch. You can change git pull to do a rebase instead of a merge with git pull --rebase and by default by setting pull.rebase. See git-config and Git Branching - Rebasing.
Break up large features into a series of smaller features. This is a skill beyond the scope of this answer, but often a big change can be broken down into a series of smaller refactorings.
Eliminate incidental fixup commits. If you need to fix something in the previous commit, instead of making a new commit "amend" your changes to the previous one with git commit --amend.
For a general cleanup, do an interactive rebase and squash your incidental commits individually. Use fixup.
$ git rebase -i master
pick abcd1234 feature: do that thing
fixup 1234dcba whoops, had a typo in that thing
fixup b33fdead docs: document that thing
fixup afdcefff test: test that thing
fixup deadb33f fix that thing
pick efga1389 feature: did another thing
You had six commits, but you only really did two things. Now you will have just two commits for doing two things.
Using these techniques you can bring your PRs down to a handful of well thought out commits, each conveying important information to the reviewer and future developers wondering why the code was written that way.
See Rewriting History for more.

Yes, they show up as a single commit. That's because GitHub only counts commits that end up on the default branch, and when you squash a PR, you end up with one commit on the default branch.
I personally don't worry about my contribution graph, so this doesn't matter to me. However, I also don't use squash and merge, since I write nice, bisectable commits with good commit messages, and squash and merge destroys that. If it's important to you not to reduce the work that a contributor has made down to a single commit, then you would need a merge strategy whose goal isn't explicitly to destroy history.

Related

How to revert a PR when there's no revert option on Github?

A PR was accidentally merged into main before it had been properly sanitized which I think has resulted in their being no revert option. The lack of an option suggests that it is not possible/simple?
https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/reverting-a-pull-request
I have write permissions to the repo in question.
A revert is just a commit like any other commit. So, you can certainly revert the merge commit and push that, possibly as a PR if you're not able to push directly to main.
However, note that this reverses the effect of the merge without undoing the topology. You won't be able to merge those same commits again later.
In theory you can force main to go backwards to a commit before this bad merge took place, erasing the unwanted commits since then, or force main to point directly to the commit at the end of the good branch — namely by using a hard reset. But in practice, where you're sharing this repo with others, that would be a pretty terrible idea.

Does GitHub retain commit history for squash merged PRs indefinitely?

Our team is deciding on what merge strategy to use in our repo. We're looking at squash merges for the ability to have a clean commit history. However, we want to be able to review intermediate changes if we want more detail on a particular commit - in particular, the intermediate commits on the PR that were squashed.
Normally, squashing and deleting the branch will remove all references to those intermediate commits in the reflog and git garbage collection could clean those up. However, in looking at other repos, it seems like GitHub still retains those intermediate commits.
What we're looking for is confirmation that GitHub is retaining those commit IDs in the reflog and that we're guaranteed they'll stick around. Alternatively, information telling us that's not guaranteed is also good.
Apparently it is guaranteed behavior. This document shows that you can check out pull requests locally. This will have the branch's commit history.

If squashing never alters committers, why does Github's squash-and-merge button update the committer?

In the spirit of testing the "there are no dumb questions" theory, why does Github's squash-and-merge strategy update the committer after merging a pull request?
That is, suppose I author a pull request in my fork of a project. Suppose it has two commits in it. Suppose I ask the project maintainer to now merge my pull request to master of the upstream project.
Suppose she chooses the squash-and-merge strategy so that there will be one commit at the end.
Suppose further that the merge can be accomplished via a fast-forward, i.e. as simple as possible a case as I can think of. (Fast-forward merges should just update the branch pointer, which seems to me like it would leave the commit completely unchanged.)
Why is it, then, that the latest commit on master after the squash and merge operation features me as the author (I understand that part) but the maintainer as the committer? Isn't that an alteration of a commit, and doesn't squashing and fast-forward merging ensure that commits are not altered?
Is Github silently doing the equivalent of something like git amend under the covers?
Isn't that an alteration of a commit
More than an alteration: a creation of a new commit, which reflect the changes of your two commits.
And your two commits are no longer referenced by the main repo: it references only the squashed commit.
That new commit has still you as an author, but is committed by the maintainer.

Amend merged pull request

I made a pull request which was merged to a project. It so happens that the code needs a minor modification. How can I possibly change this with no access to the master project whatsoever? Am I out of luck and I have to do a new PR?
Thanks.
Yes, you should submit another pull request.
When using any of Git's "rewriting" commands like commit --amend or rebase it is important that you avoid changing shared commits.
In its Rebasing chapter, the Git Book says:
The Perils of Rebasing
Ahh, but the bliss of rebasing isn’t without its drawbacks, which can be summed up in a single line:
Do not rebase commits that exist outside your repository.
If you follow that guideline, you’ll be fine. If you don’t, people will hate you, and you’ll be scorned by friends and family.
When you rebase stuff, you’re abandoning existing commits and creating new ones that are similar but different. If you push commits somewhere and others pull them down and base work on them, and then you rewrite those commits with git rebase and push them up again, your collaborators will have to re-merge their work and things will get messy when you try to pull their work back into yours.

Github repo squash commits on master

I'm working with a github repo where a lot of commits historically have been "bugfix", "bugfix for real this time", "ok final bugfix", "finally fixed".
These were committed directly to master. How can I squash them?
Fromt his post a year ago - it basically sounds like this is bad, want to squash multiple commits in github. Has anything changed in the past year?
The answer today is basically the same: Squashing these commits is possible, but rewriting shared history is something to be strongly avoided in Git.
Imagine that you and I each have a copy of some repository that also exists on GitHub:
A---B---C
You notice that commits B and C should really have been committed together, so you squash these commits in your local copy. You now have
A---D
where D is a combination of B and C, while GitHub and I still have
A---B---C
At this point, even though the file content is the same everywhere, our commit IDs have diverged. Now you can't push to GitHub without --force, because GitHub's master branch contains two commits that are no longer present in your history.
If you do use --force you can make GitHub accept your changes, but now my repository contains commit objects that are no longer present upstream. I can't push to GitHub without using --force (which will invalidate your changes) or without doing a relatively funky merge to bring your changes in, probably rebasing my work, etc. And that's only possible if you communicate with me outside of Git to tell me what you've done.
This gets even messier with more developers (imaging doing this on the Linux kernel repository!) and with more work being done concurrently.
Really, any time you're tempted to git push --force, sit back and think for a moment. You're probably doing something that should only be done with an extremely good reason.
My recommendation is to accept that your history is a bit messy, but to try to improve things going forward. These commits can be cleaned up locally, before you push to GitHub (or share with other developers). Work in feature branches, use cherry-pick, rebase, etc. to clean up the commit history if necessary, then push.
Squashing is something which is used to merge a lot of commits into one. If you want to clean up last serval commit's check your last git log's by using
git log
this will look something like this
* df71a27 - (HEAD feature_x) Updated CSS for new elements (4 minutes ago)
* ba9dd9a - Added new elements to page design (15 minutes ago)
* f392171 - Added new feature X (1 day ago)
* d7322aa - (origin/feature_x) Proof of concept for feature X (3 days ago)
now if you want to squash last three commit's then
git rebase -i HEAD~3
by doing this you'll get into editor like this
pick f392171 Added new feature X
pick ba9dd9a Added new elements to page design
pick df71a27 Updated CSS for new elements
Edit the one who you want to squash like this
pick f392171 Added new feature X
squash ba9dd9a Added new elements to page design
squash df71a27 Updated CSS for new elements
When done, save and quit your editor. Git will now squash the commits into one. All done!