The recent post and hype about the Facebook, Google and Microsoft monorepos should make us ask the question what our systems for source control is supposed to do really.
save changes to a source code
save changes to big binary assets
annotate those changes
annotate the files themselves
tagging versions
signing of code
code review
handle regressions testing
collaborating (ACL, DCVS, official monkey patching etc)
merging
search on the whole code base
refactoring on large code bases
All these things have uses but they are not really supposed to be tied to one VCS, we have very basic needs when working with source code streamlining the UX for that workflow might be more important and in the same time opening up for easy access to the other stuff.- git add -e
- git rebase -i --autostash <upstream>
- git checkout -f -- <file> (to undo changes)
- git diff/log (of course)
- git reset HEAD^ (to undo the head commit but leave its changes extant in the workspace so I can then git add -e and commit them in logical units)
In hierarchical logs, a merge commit stands for the series of commits that are being merged. You can then unfold such commits and view the series of commits as a nested list of commits (which may again contain merge commits).
Think of a merge commit as the equivalent of a procedure call where the procedure body is the series of commits being merged.
(Note that there are other ways to visualize version graphs with merge commits; this is just the simplest way to do it and could actually be easily added on top of Git.)
Rebasing has two problems. It discards the original version structure and it can create commits that never build or don't pass tests (because they never existed as such).
Frequent use of rebasing is almost always an indication that a VCS is lacking important functionality.
None of that information is too relevant. If you have the commits individually cherry picked in your stream, that's most of the info you ever need about those commits. There is some earlier version of those commits in a different stream, where they look different. Usually, who cares.
The way to track that is some sort of additional meta-data. An example of this is the Gerrit Change-ID.
Rebase as a tool is not inherently bad but it is definitely not simpler than merge - it introduces additional considerations, requires a deeper understanding of git for effective use and is a dangerous tool in the hands of people who do not understand what it is doing and in my experience most teams that are using it as a core part of their workflow are doing so for the wrong reasons (generally because of a fundamental misunderstanding of how branching and merging works in git and why it works that way).
Rebase is basically just cherry picks. You can rewind a branch and then cherry-pick, so that the picks are non-fastforward. That's rewriting history. Cherry picking without rolling back is fastforward, and so doesn't rewrite history.
The Gerrit review system on top of Git is based on cherry-picking; it doesn't rewrite history.
If some developers are collaborating on a feature which is on a branch, they could agree from time to time to rebase that branch to a newer mainline.
Whether or not that is done by a history rewrite simply hinges on whether the same branch name is used for the rebased branch or not. The rebase is what it is: if you plant that rewrite as the original branch name, then you have a non-fastforward change. If a new branch name is made, then it isn't a rewrite.
Merging a feature branch onto a trunk can always be done in a fastforward way using rebase/cherry-pick.
Rebasing is provably simpler than merge. Merge depends on complications in the git object representation which could be removed while rebase remains what it is. If you only ever rebase, you never see a commit with multiple parents; the feature is superfluous and turns git histories into hairballs.
Rebase might give you a "simpler" end result in terms of what the history looks like but conceptually it is much less simple in terms of its mechanism and its implications (e.g. rebasing a branch with multiple contributors screws up the audit trail as it now looks like they made their changes at a different time and in a different context to when they actually did) than the idea of a graph with two branches and a merge commit.
I have seen teams with limited git experience switch from habitually rebasing public branches to accepting merge commits and suddenly cure a whole host of workflow problems.
If you can rebase directly onto a fresh branch (not something I've seen) then I am fairly sure that that's not part of your average workflow - establishing new branches every time you want to update from trunk comes with its own communication overhead too.
> > it introduces additional considerations, requires a deeper understanding of git for effective use and is a dangerous tool in the hands of people who do not understand what it is doing
I am taught git with rebase (though merge when I use hg) so I am already too used to it. Branching then rebase is not that difficult if you keep your workflow consistent and quick iteration. You should be up to date whenever possible. Amending and rewriting history/comment also requires using rebase.
YMMV.
As soon as a tree is pushes, those changes become public, and you need to explicitly force the history rewriting operations.
This is part of the " safe defaults" approach of mercurial.
> git rebase
Yeah... :)
I find this simpler and cleaner than introducing a series of merge commits in my local branch.
When we go back and view those changes, they are all in terms of this codebase, not the original changes that do not apply cleanly to this codebase. That's a big problem with git merges: the merge itself is one huge jump that collapses all the changes. The original changes are traceable in its lineage through the second parent, but those are the verbatim original changes, not the merged changes.
git init
git clone
git checkout
git commit
git commit -m
git commit —amend
git rebase
git add/rm/diff [—cached]
git push
git branch
and a few more I can’t remember exactly.
I try to keep my git workflow simple. The most complex is probably checkout abd rebase with several different branches.