Working with Git - bennycode/welovecoding.github.io Wiki

Terminology

A pull request does not include tags. A pull request is only a pointer to a thread of commits (a branch) in your repository that you're proposing another repository to merge.

Update fork from origin

git remote add upstream [email protected]:Ashlar/binance-api-node.git
git fetch upstream
git rebase upstream/master
git push origin master --force

Find Git config on Windows

Viewing diffs

Comparing old with new on GitHub:

<<<<<<< below/is/the/PR
    const gotSingleInstanceLock = app.requestSingleInstanceLock();
    logger.info('Checking if we are the first instance...', gotSingleInstanceLock);
=======
    isFirstInstance = app.requestSingleInstanceLock();
    logger.info('Checking if we are the first instance ...', isFirstInstance);
>>>>>>> above/is/the/current

Index tree: File from "below/is/the/PR" before automatic/manual merge
Working tree: File from "below/is/the/PR" after automatic/manual merge

Git introduction

Cherry pick

git cherry-pick 9a4cf4e6834fd29ea6c12fb1aaeb86feff181e52

Add Origin

git remote add bennyn [email protected]:bennyn/project.git
git add .
git commit -m "First commit"
git push bennyn master

Bisect

Given:

Usage:

git bisect start
git bisect good 651462078c77048072148f648b2c8544c9842730
git bisect bad c3275868b8cca4c8c837f644a1a1fc5aceff9815

When git bisect checks out your code, then test it and answer with git bisect good or with git bisect bad.

Git Alias

git config --global alias.nimm checkout

Common mistakes

Error

! [remote rejected] master -> master (missing necessary objects)
error: failed to push some refs

Solution

Create aliases

git config --global alias.add-commit '!git add -A && git commit'
git add-commit -m 'My commit message'

Checkout a specific commit

Use git checkout <sha1> to check out a particular commit.

Revert to a specific commit

Note: This reverts also the history.

git reset --hard e34ab3065f30126bd239d13c62102e98d3c6f134
git push --force

Note 2:

If you run in this situation, then use git revert instead of git reset. Git revert will revert things with new commits. It also supports ranges:

# This will revert the last three commits:
git revert HEAD~3..HEAD

Revert last commit

git reset --soft HEAD~ is already sufficient!

git reset --soft HEAD~1
git commit -am "Reverted last commit."
git push origin master --force

Alternative

git push origin +sha_code:master

Change last commit message

git commit --amend -m "New commit message"

Revert unpushed commits?

git reset --hard origin/master

Create branch

git checkout -b branch_name
git commit -am "Message"
git push origin branch_name

Merge branch 'master' into branch 'new_feature'

git checkout master
git pull
git checkout new_feature
git merge master
git push

Resolve merge conflicts

Commit message after merges

Even easier:

If you ran into a rebase, then cancel it by executing git merge --abort.

Example diff:

<div>Until here, everything looks the same</div>
<<<<<<< HEAD
<div>This is stuff which is available on the other side</div>   
=======
<div>This is stuff which is new from your side</div>
>>>>>>> Commit message
<div>Here the file looks the same again...</div>

Create new repository

touch README.md
git init
git add README.md
git commit -m "First commit"
git remote add origin https://github.com/name/repository.git
#  git push --set-upstream origin master
git push -u origin master

Reset Changes

If you made mistakes during a merge and you have not committed your mistaken changes yet, then you can undo them with git reset --hard.

Add all

Instead of doing git add file-a and git add file-b, you can just do git add . if you want to add all modified files.

Ignore Patterns

/project/*/*.js
/project/*/*/*.js
/project/*/*/*/*.js
/project/*/*/*/*/*.js

->

/project/**/*.js

Git stash

git add .
git stash
git stash apply

Merge / Squash pushed commits

The last 4...

git reset --soft HEAD~4
git commit -am "Squashed the last 4 commits"
git push --force origin branch_name

Or:

Squash commits locally with git rebase -i origin/master~4 master and then force push with git push origin +master.

Note: Don't do that if you have co-workers on your branch! Because you can easily reset their changes if they push in between.

Squash all commits

git reset $(git commit-tree HEAD^{tree} -m "Initial commit")

Working with submodules

Example

libsodium is included as a submodule so make sure you either git clone --recursive or git submodule update --init --recursive right after cloning.

Using patch files

If you haven't commited the changes, then:

# Batch file will be saved into the root directory of the repository
git diff > mypatch.patch
git apply mypatch.diff

Update a fork from the original repository

Foreword: Your fork is the "origin" and the repository you forked from is the "upstream".

Let's assume that you cloned already your fork to your computer with a command like this:

git clone [email protected]:your_name/project_name.git
cd project_name

If that is given then you need to continue in this order:

  1. Add the "upstream" to your cloned repository ("origin"):
git remote add upstream [email protected]:original_author/project_name.git
  1. Fetch the commits (and branches) from the "upstream":
git fetch upstream
  1. Switch to the "master" branch of the "origin" (your fork):
git checkout master
  1. Stash the changes of your "master" branch:
git stash
  1. Merge the changes from the "master" branch of the "upstream" into your the "master" branch of your "origin":
git merge upstream/master
  1. Resolve merge conflicts if any and commit your merge
git commit -am "Merged from upstream"
  1. Push the changes to your fork
git push
  1. Get back your stashed changed (if any)
git stash pop
  1. There is no step 9 :dancer:

GitHub

Syllabus

Clarification for

This branch is 1 commit ahead of yathit:master.
git merge
Merge made by the 'recursive' strategy.
git tag -a v1.3.3 -m "bug fixes"
git push origin master v1.3.3

Merging via command line**

From your project repository, bring in the changes and test.

git fetch origin
git checkout -b call-banner origin/call-banner
git merge staging

Merge the changes and update on GitHub

git checkout staging
git merge --no-ff call-banner
git push origin staging

Git configuration

Core settings

1. Don't automatically handle line endings

git config --global core.autocrlf false

Will add the following to %USERPROFILE%\.gitconfig:

[core]
  autocrlf = false

Overview of Windows variables: https://technet.microsoft.com/en-us/library/cc749104(v=ws.10).aspx

2. Enable file system caching

git config --global core.fscache true

Will add the following to %USERPROFILE%\.gitconfig:

[core]
  autocrlf = false
  fscache = true

User settings

Identity

git config --global user.email "[email protected]"
git config --global user.name "Firstname Lastname"
[core]
  autocrlf = false
  fscache = true
[user]
  email = [email protected]
  name = Benny Neugebauer

Pro-Tip: If you change the identity but you already have commits, then you can reset the author for those commits with: git commit --amend --reset-author.

Credentials

Save password in credential helper

git config --global credential.helper wincred
git config --global credential.helper osxkeychain
git config credential.helper 'cache'
git config credential.helper 'cache --timeout=1800'

Note: Every cloned repository has also local settings in .git\config which override the global settings. Here is an example of a cloned repository's configuration:

[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	symlinks = false
	ignorecase = true
	hideDotFiles = dotGitOnly
[remote "origin"]
	url = https://github.com/bennyn/tagebuch.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

git remote set-url origin [email protected]:username/repo.git

Push settings

Default Push method

warning: push.default is unset; its implicit value is changing in
Git 2.0 from 'matching' to 'simple'. To squelch this message
and maintain the current behavior after the default changes, use:

  git config --global push.default matching

To squelch this message and adopt the new behavior now, use:

  git config --global push.default simple

When push.default is set to 'matching', git will push local branches
to the remote branches that already exist with the same name.

In Git 2.0, Git will default to the more conservative 'simple'
behavior, which only pushes the current branch to the corresponding
remote branch that 'git pull' uses to update the current branch.

See 'git help config' and search for 'push.default' for further information.
(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode
'current' instead of 'simple' if you sometimes use older versions of Git)

Things to find out

cd kitchensink
git remote add upstream -m master git://github.com/openshift/kitchensink-example.git
git pull -s recursive -X theirs upstream master

GitHub

GitHub URL schemas

Links

Terminology

Backup

# https://api.github.com/users/bennyn/repos?page=1&per_page=100

# git://github.com/bennyn/amplify.git
USER=YOURUSERNAME;PAGE=1; curl "https://api.github.com/users/$USER/repos?page=$PAGE&per_page=100" | grep -e 'git_url*' | cut -d \" -f 4 | xargs -L1 git clone

# [email protected]:bennyn/amplify.git
USER=YOURUSERNAME;PAGE=1; curl "https://api.github.com/users/$USER/repos?page=$PAGE&per_page=100" | grep -e 'ssh_url*' | cut -d \" -f 4 | xargs -L1 git clone
```

## Similarity between git stash pop & git stash apply

## Update a fork with the original

- https://help.github.com/articles/resolving-merge-conflicts-after-a-git-rebase/

git pull https://github.com/caiogondim/logdown.js.git master
[fix conflicts]
git stage
git rebase --continue [don't do a commit before]
[fix conflicts, if there are new ones]
git stage
git rebase --continue [don't do a commit before]
[finally do:]
git push origin length-option-logdown -f

## When losing the upstream

```bash
git branch --set-upstream-to=origin/db-improvement db-improvement
```

## .gitconfig

GPG in `%USERPROFILE%\.gitconfig`

```yaml
[user]
	name = Benny Neugebauer
	email = [email protected]
	signingKey = ABC
[gc]
	autoDetach = false
[gpg]
	program = C:\\Program Files (x86)\\GNU\\GnuPG\\gpg2.exe
[commit]
	gpgSign = true
```

## Adding new files

```bash
git status
git add filename.js
git commit -am "Staged filename.js"
```

Or

```bash
git -am "Staged filename.js"
```

But `git -am` only works for already staged files (files which are already know to Git and versioned by it).

Multiple files can be added like:

```bash
git add file-name-1.php file-name-2.js file-name-3.html
```

Regular expressions are also valid:

```bash
git add dist/**/*
```

There is also [Git interactive staging](https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging):

```bash
git add -i
```

A `git add file.js` can be undone with `git reset file.js`.

## Line endings
- http://stackoverflow.com/questions/10418975/how-to-change-line-ending-settings

## Commit "nothing"

```bash
git commit --allow-empty -m "Trigger Action"
```

## Add something to an already pushed commit

```js
git commit --amend
git push -f
```

## Update your fork with GitHub origin

```bash
git remote add github [email protected]:askmike/gekko.git
git fetch github
git merge github/develop
```

## Force Push

```bash
git commit --no-verify -m "This commit will go through"
git push --force
```