75
Carlos Duarte Do Nascimento @chesterbr • http://chester.me git fail --force make it up with your pull requests

git fail --force (make it up with your pull requests)

Embed Size (px)

Citation preview

Carlos Duarte Do Nascimento@chesterbr • http://chester.me

git fail --forcemake it up with your pull requests

Let’s write some code!

Whoops...

WTF?

It’s either “git for dummies”...

Hovertext: “If that doesn't fix it, git.txtcontains the phone number of a friend

of mine who understands git.Just wait through a few minutes of 'It's

really pretty simple, just think ofbranches as...' and eventually you'll learnthe commands that will fix everything.”

Git - 30/Out/2015https://xkcd.com/1597/

Neither rookie nor expert

Good professionals will try to becomeproficient in their tools - not become

specialists in all of them

Expert Advice

● “Do a git pull once in a while”● “Never use git pull” ● “Always rebase!”● “Never rebase!!!”● ...

How does that end?

Proposal

Revisit git concepts from theperspective of a typical workflow,avoiding theory overload and the

abuse of rules and cookbooks

Carlos Duarte Do Nascimento(Chester)

@chesterbr • http://chester.meGit non-specialist

https://www.shopify.com/careers

Git

A system that allows people to workwith source code in an orderly and

simultaneous fashion

Commit

When a meaningful change is made,you take it to the stage in order to

take a snapshot (commit)A92347C2…1F2493E34: Increase submit button size

DescriptionID

Commit == snapshot

“Git is all about composing and savingsnapshots of your project and thenworking with and comparing those

snapshots”

http://gitref.org/basic/

Branch

Successive commits form a timeline

One can commit into alternativetimelines (branches) and later integratethose with the main timeline (master)

Group workYour commits “live” in your local

repository (.git/)

You can push commits to otherpeople’s repositories (remotes), and

also pull commits from there

Organizing your groupThis flow of commits/branches can beorganized in several ways (workflows)

A central repository thatenables code reviews by means

of pull requests helps a lot...

● Refresh master (remote ⇒ local)● Create new branch from there● Commits, commits, commits!● Push, PR (my branch ⇒ master)●

But what if...

● ...CI* fails?● ...other devs suggest changes?● ...master changed while I worked?

*Continuous Integration

Conflict!

Image © 1995 GAINAX/Project Eva.

Manual merge$ git checkout master$ git pull$ git checkout my-branch...$ git commit$ git push...$ git push --force

#NOT

It can get really bad● Irreconcilable conflicts● Alien commits on my PR● Commit is there, code is not● The @#%@ button is still grey● ...

How can we fix/avoid that?

By understanding what is happening ona pull request to identify (and avoid)traps, or, as a last resource, to rebuild

our PR with minimal effort

Pull request

Pull Merge request

“wants to merge?”

git merge

Includes commits from another branch inthe current one, without changing them

(an extra commit at the end willconsolidate changes from both sides)

How can that go wrong?

Consolidating changes from twodifferent timelines becomes more

complex as they diverge

Avoid the problem

Whenever possible, create small,isolated and short-living branches

If you can’t avoid it

There are several ways to make abranch compatible with master again

Our workflow works well with rebase

git rebase

Rebuild the branch from its originalpoint (by default), creating new commitsidentical to the original ones (by default)

(hint: these defaults won’t help you)

What can I do with rebase?

● (re-)base your changes on a morerecent master(e.g.: git fetch; git rebase origin/master)

● Simplify your commits(e.g.: git rebase --interactive master)

How can that go wrong?

Updating the branch and simplifyingcommits at the same time is tricky

Rewriting a branch that is alreadypublished causes incompatibilities

PR prep suggestion (1)Recreate your branch from a

more recent master(without changing the commits)

git checkout master git pull

git checkout my-branch git rebase master

PR prep suggestion (2)

Simplify your commits(without changing the branch point)

git rebase –-interactive master

Suggestion ≠ rule

If the master didn’t change (much),don’t botter updating

If your commits are clear,don’t bother interacting

After the PR is created

New commits can be added to theremote, just git push them

Rebase, however, isn’t that simple

(why?)

Rebases change the past!!!

(uhhh... so what?)Image © Universal Studios. All rights Reserved

Is that a real problem?

A git push from a rebased branch hasto replace the remote branch history

(hence the --force requirement)

Workflow to the rescue

If the workflow saysonly the creator commits on a PR,rebasing its branchshould not cause

any troubleImage © 2016 Twentieth Century Fox Film Corporation.

Avoiding further troubleJust like before the first push, don’t

change the start point andsimplify commits at the same time

A new commit is always lesstricky than a rebase

Master is sacredBranches / pull requests are only

relevant during their lifetime

It hit the fan - now what?

git cherry-pick

Reproduces in your branch thechanges from a single commit

(even a branch-less one)

git cherry-pick id

Cherry-pick good commits

Instead of recreating changes manually,we can cherry-pick the original

commits into a fresh branch

But we need to find those commits...

git log x git reflog

git log lists commits created in thecurrent branch (lots of search options)

git reflog lists any operations thataffected the local repository in any way

git reflog

f84195a HEAD@{0}: checkout: moving from 1468-more-resilience-on-ind5a8868 HEAD@{1}: commit: Log the invalid listing on offer-less of79e7c98 HEAD@{2}: commit: Better test naming and more detailed log31e2ac1 HEAD@{3}: checkout: moving from master to 1468-more-resilif84195a HEAD@{4}: rebase finished: returning to refs/heads/masterf84195a HEAD@{5}: pull --rebase --autostash: checkout f84195a626e9ac12705 HEAD@{6}: rebase finished: returning to refs/heads/masterac12705 HEAD@{7}: pull --rebase --autostash: checkout ac127053051c...

#howto

1. Find all the commits that weresupposed to be on your PR

git log • git reflog •

#howto

2. Sync your master with the serverand create a brand new branch from it

git checkout mastergit pull

git checkout -b new-branch

#howto

3. Apply the commits

git cherry-pick id1 id2 id3...

#howto4. Replace the old branch with the new

one (on local and remote repos)

git checkout master git branch -D my-branch git branch -m new-branch my-branch

git checkout my-branch git push –-set-upstream origin my-branch --force

Life is good again!

Conclusion (1)

You don’t need to know everything about git, but it’s a good idea to have asolid understanding of some concepts

(e.g.: commit, branch, merge, rebase)

Conclusion (2)

As long as it was committed, there isalways a way to recover your work.

Avoiding push accidents

Image © CAPCOM Ltd.. All rights Reserved

Don’t use the --force, Luke

Make a habit of trying “vanilla” gitpush before adding any arguments

(e.g., origin my-branch or --force)

On a new branch$ git checkout -b new-branchSwitched to a new branch 'new-branch'$ git commit -am "my changes"[new-branch eabe2c9] my changes 1 file changed, 2 insertions(+)$ git pushfatal: The current branch new-branch has no upstream branchTo push the current branch and set the remote as upstream,use

git push --set-upstream origin new-branch

$ git push --set-upstream origin new-branch

After a rebase

$ git rebase -i masterSwitched to a new branch 'new-branch'$ git pushTo github.com:Shopify/some-repo.git ! [rejected] new-branch -> new-branch (non-fast-forward)error: failed to push some refs to 'github.com:Shopify/some-repo.git'hint: Updates were rejected because the tip of your currentbranch is behind$ git push --force

Know where you areAlways show the current branch onyour command line prompt (bash):

export PS1="\h:\W \u\[\033[32m\]\$(__git_ps1)\[\033[00m\]\$ "

MyComputer:myproject me (my-branch)$

GUI x CLI

Image CC BY-SA Wikipedia user Sandstein

gitk

GitHub Desktop

Tig

Stay freshUpdate your master to the latest

remote without leaving your branchgit pull --rebase --autostash

For git < 2.9, use the git-up gem gem install git-up git up

Non-brute force

Rewrite history, but only if no one elseadded commits to the branch

git push --force-with-lease

Branch prefix shortcutsgit push --delete my-branchgit push --force my-branch

can be shortened togit push :my-branchgit push +my-branch

(just be careful not to add + by habit)

Thank you!

Carlos Duarte Do Nascimento@chesterbr • http://chester.me

shopify.com/careers

http://slideshare.net/chesterbr

This presentation is available under the Creative Commons “by-nc” 3.0 license(available at https://creativecommons.org/licenses/by-nc/3.0/),

noticing the exceptions below.

Images and text from third parties were included (with due credits wherever possible)under a fair use assumption (or, for Brazilian media, under Art. 46 of Law 9610/98)and/or under their respective licenses. Omissions are unintended and corrections

welcome. Such content is excluded from the license above.

GitHub, the GitHub logo and mascot are trademarks of GitHub, Inc.Shopify and the Shopify logo are trademaks of Shopify, Inc.

The opinions stated here belong solely to the author, not offically representing hisemployer’s opinions, nor any of of the persons or companies mentioned in any extent.

Credits And License