Hacker Newsnew | past | comments | ask | show | jobs | submit | chenhan's commentslogin

It is a problem in mailing lists but GitHub has good tooling around it. Every time you force-push, GitHub keeps and provides direct links to the old commit, the new commit and the diff between the two commits. Every force push appears as its own diff on the GitHub PR page.

How is GitLab doing in this area? Does GitLab show diffs for force-pushes?


> Every time you force-push, GitHub keeps and provides direct links to the old commit, the new commit and the diff between the two commits.

Not in my experience. Here's one of my pull requests:

https://github.com/mchehab/zbar/pull/64

The maintainer reviewed some of the changes and I revised my commits as a result. The review is correctly marked as outdated. Clicking on the file name tells me the commit cannot be found.

> We went looking everywhere, but couldn’t find those commits.

> Sometimes commits can disappear after a force-push. Head back to the latest changes here.


Your pull request shows exactly what I am talking about. For every force-push it has direct links to the old commit, the new commit and the diff.

Pick the first force push in your PR. It says

> matheusmoreira force-pushed the matheusmoreira:binary-decoding branch from aec04b3 to 87a0b3c on 5 Nov 2019

Click on 'force-pushed'. That's the diff of force-push.

Click on 'aec04b3'. That's the commit before force-push.

Click on '87a0b3c'. That's the new commit in the force-push.


You're right. I never realized those messages contained links. They do lead me to the old commits.

I don't understand why the code review can't find the commit though.


> For every force-push it has direct links to the old commit, the new commit and the diff.

It's there a way to see the diff between commits that are/were not at the HEAD of the branch? That is, doing something like:

  git diff aec04b3^.. 87a0b3c^


This is a good article that covers how to communicate in a pull request. I think there are two other essentials in making good pull requests.

1. Good commit messages. Follow this guide: https://chris.beams.io/posts/git-commit/

2. Following the pull request workflow correctly. Follow this guide: https://github.com/susam/gitpr

Writing good and consistent commit messages make the commit log easy to read and search.

Pull request workflow is equally important. It is kind of a rules of engagement that co-developers follow to keep working on their stuff concurrently. It keeps unnecessary merges to minimum and keeps the commit history clean.

By following these two things, you are not only going to be nice to your co-developers but you are going to be nice to your managers and release departments too who could look at your commit log and figure out what bugs were fixed and what features were released.


I will elaborate why I think the two points in my comment above are important.

Git Rebase, Git bisect and other operations display the commit summary line when they get stuck with merge conflicts or find an issue, so I find good commit summary lines very helpful during those operations. Without good commit messages, resolving issues during those operations can get confusing. This is one of the reasons why writing good commit messages are important.

I see many developers working on their PR branch and constantly merging new commits from master into the PR branch as the master keeps moving ahead. It creates a big mess of merges in both directions-- (A) from master to PR branch during development and (B) later again from PR branch to master when the PR gets merged. The first set of merges from master to PR branch are totally unnecessary. It adds nothing meaningful to the commit history. They are just extra commits to scroll through while looking at git log. Every time the master branch moves ahead, just rebase your PR branch on master. The commit history remains clean and minimal. A good PR workflow teaches you that.

Having said that, merge commits from PR branch to master are totally fine. They do add something meaningful. They show the point at which a PR was merged into the main project.


If you share a development branch with someone, then you should prefer merging over rebasing because rebasing changes rewrites the commit history, causing the locally checked out branches among collaborators to disagree. You never know when someone will need to take your branch to develop on, so generally it’s a good idea to merge over rebase. When master is merged into your PR branch, the fork point is forwarded to the last master commit, so you shouldn’t have any trouble merging back into master.


I think the OPs concern was more with the commit history in the PR being polluted with merge commits.

I do agree that merge commits can obfuscate history somewhat. However, I agree with dimes that its better to not rewrite history just to keep the commit history clean... the cleanliness is not worth the price for inability to collaborate effectively.

Also, any professional code review tool will not let merge commits affect your review. Highly recommend reviewable.io for this.


I think rebase is fine, you just need to synchronise with the people working with you on the branch. There shouldn't be more than 1 or 2, otherwise you're probably doing something wrong.

Also, I only rebase when it makes sense in that case, you need something from master or you're about to merge back into master, so disruption should be minimal.


> If you share a development branch with someone, then you should prefer merging over rebasing

Your parent comment is suggesting rebase only for pulling latest changes in master into your pull request.

For merging someone's pull request to the team's master, sure use a merge commit.

But if you are working on a pull request and while you are working on it, the team's master gets updated and now you want to base your work on the recent master, by all means, use git rebase. That is what it is meant for, to rebase your work on another work. It's in the name itself.

Right tool for the right job.


I partially agree. While I use git rebase on my branches, if somebody refuses to do it because of whatever reason and has on their branch a bunch of merge commits (usually `develop` into their branch) due to a stale PR, or a bunch of typo fixes or, worst of all, a bunch of emoji commits - so be it. BUT when they merge it back into develop/master I expect all that silliness to be squashed to one or more commits with clear commit messages.

It boils down to: what you are doing on your own branches is your thing, but when interacting with shared ones do so with some professionalism and decency.


Using a rebase to update from master will cause conflicts for anyone else working on the PR branch. To understand why, imagine a developer branches from master at commit A, and then creates two commits on the branch B and C. In the meantime, master gets updated with commits D and E. Rebasing in this situation, results in a branch that looks like A, D, E, F, G, where F and G contain the same content as B and C, but are now tracked under different hashes. If a collaborator has this branch, git will report the local branch has two different commits (B and C) and that the remote branch has two different commits (F and G). Doing a typical “git pull” in this situation will lead to merge conflicts in everything touched by commits B and C. You can work around this specific problem by using git pull —rebase. However, git works best when the remote history is immutable. If you have a specific commit in your PR that you want someone to look at, you send them a link to it using the commit hash. Once you rebase, that commit hash will no longer point to anything. Rebasing is useful for completely changing the branch your PR branch is cut from. But once you rebase from one base branch to another, you should then continue to merge from the new base branch.


> Using a rebase to update from master will cause conflicts for anyone else working on the PR branch.

The best way to handle that is to run git stash save, git fetch origin, then run git rebase @{u} to rebase your local branch on top of the new upstream branch. Then run git stash pop to apply any uncommitted changes.

> Doing a typical “git pull” in this situation will lead to merge conflicts

This is why I never use git pull, and always run git fetch instead. This allows me decide whether I want to merge the upstream changes, rebase on top of them, or just run git reset --hard to just use the upstream branch as is.

> Once you rebase, that commit hash will no longer point to anything.

Unless git gc deleted the dangling commits (along associated trees and boobs), the hash value will still show the commit. In fact, it's possible to show a diff from that commit to the corresponding commit in the rebased branch.


Is it really sending 1.3 MB of content over the wire? My network tab in browser shows only 75 KB of transfer size.


When I read this, I immediately began thinking if there is someone I know who has been involved in both science/math and TV/movies and the name that popped up for me was Carl Sagan. Carl Sagan has Erdos-Bacon number of 6.


I never really understood Git until I read this tutorial: https://github.com/susam/gitpr

Things began to click for me as soon as I read this in its intro section:

> Beginners to this workflow should always remember that a Git branch is not a container of commits, but rather a lightweight moving pointer that points to a commit in the commit history.

    A---B---C
            ↑
         (master)
> When a new commit is made in a branch, its branch pointer simply moves to point to the last commit in the branch.

    A---B---C---D
                ↑
             (master)
> A branch is merely a pointer to the tip of a series of commits. With this little thing in mind, seemingly complex operations like rebase and fast-forward merges become easy to understand and use.

This "moving pointer" model of Git branches led me to instant enlightenment. Now I can apply this model to other complicated operations too like conflict resolution during rebase, interactive rebase, force pushes, etc.

If I had to select a single most important concept in Git, I would say it is this: "A branch is merely a pointer to the tip of a series of commits."


And you can see this structure if you add to any "git log" command "--graph --oneline --decorate --color". IIRC some of those are unnecessary in recent versions of git, I just remember needing all of them at the point I started using it regularly.

I have a bash function for it (with a ton of other customizations, but it boils down to this):

  function pwlog() {
    git log "$@" --graph --oneline --decorate --color | less -SEXIER
  }
  pwlog --all -20
(...in that "less" command, "S" truncates instead of wraps lines, one "E" exits at EOF, "X" prevents screen-clearing, and "R" is to keep the color output. The second "E" does nothing special, it and "I" (case-insensitive search) are just to complete the word)


You can also set $GIT_PAGER/core.pager/$PAGER and create an alias to accomplish this:

  #export PAGER='less -SEXIER'
  #export GIT_PAGER='less -SEXIER'
  git config --global core.pager 'less -SEXIER'
  git config --global alias.l 'log --graph --oneline --decorate --color'
  # git diff ~/.gitconfig
  git l
core.pager: https://git-scm.com/docs/git-config#Documentation/git-config...

> The order of preference is the $GIT_PAGER environment variable, then core.pager configuration, then $PAGER, and then the default chosen at compile time (usually less).


>This "moving pointer" model of Git branches led me to instant enlightenment.

As opposed to any other VCS? Feels like that model is the only one that works with SVN too. I struggle to see how "branch is a container of commits" is a viable model to begin with.


It's a good-enough description of SVN, where branches exist in the same directory tree, commits are tied to the branch by way of the path, and the merge tools are "merge this batch of commits from branch A to trunk" (you don't have to take the whole branch at once).

One of the biggest hurdles my co-workers have had learning git after having used svn for years is the "bucket of commits" mental model they've built up for branches. A common question is how to merge a single commit.


This is closer to how I would describe HG and SVN. Branches can be traced from start to merge, they are heavy. You know which commits came from what.

In git you can lose track of what came from what branch when you start merging multiple back and forth, this does happen with svn.


Mercurial branches are different from git branches; they're topological structures that emerge when a revision gets an alternate child. They're like growing and stopping lines of development. They exist on their own, Mercurial simply allows to give them names. What git calls branches in Mercurial is called bookmarks.


> A branch is merely a pointer to the tip of a series of commits.

But this is not actually correct because a branch can often point to a commit that is not the tip.


It is the tip for that branch. Even if there exist other commits building on the commit the current branch points to, the pointer is still at the tip for that branch.

The point is that a branch is simply a pointer to a commit that automatically encapsulates all of the parent commits.


I think I see what it means though. The branch uses that commit as a new tip to then branch off of, not necessarily meaning a new branch starts at the existing 'tip'.


For the curious, the ISO standard is ISO/IEC 14977. It is available here: https://standards.iso.org/ittf/PubliclyAvailableStandards/

Direct link to the standard: https://standards.iso.org/ittf/PubliclyAvailableStandards/s0...

But of course, as shanka commented, it isn't a standard that is followed practically. This is just a demonstration of https://xkcd.com/927/ in real life.


GCP documentation is the worst I have come across so far. The GCP documentation seems to have multiple personalities. It is as if the different parts of the documentation were written by different teams in different corners of the company.

I have to often disregard the documentation and get into the gcloud (their Python-based CLI and API) to understand what the heck is going on and their CLI/API code is no good either. Layers and layers of abstraction in their code only to make some REST API calls. The amount of over-engineering and abstraction that is present in their Python code would put even Java SimpleBeanFactoryAwareAspectInstanceFactory developers to shame.


Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: