GIT intro


27 Mar

Git Basics

The major difference between Git and any other VCS (Subversion and friends included) is the way Git thinks about its data. Conceptually, most other systems store information as a list of file-based changes. These systems (CVS, Subversion, Perforce, Bazaar, and so on) think of the information they keep as a set of files and the changes made to each file over time.

Git doesn’t think of or store its data this way. Instead, Git thinks of its data more like a set of snapshots of a miniature filesystem. Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot. To be efficient, if files have not changed, Git doesn’t store the file again, just a link to the previous identical file it has already stored. Git thinks about its data more like a stream of snapshots.

Most operations in Git only need local files and resources to operate – generally no information is needed from another computer on your network.

Everything in Git is check-summed before it is stored and is then referred to by that checksum.

The mechanism that Git uses for this checksumming is called a SHA-1 hash.

When you do actions in Git, nearly all of them only add data to the Git database. It is hard to get the system to do anything that is not undoable or to make it erase data in any way.

Git has three main states that your files can reside in: committed, modified, and staged. Committed means that the data is safely stored in your local database. Modified means that you have changed the file but have not committed it to your database yet. Staged means that you have marked a modified file in its current version to go into your next commit snapshot.

Install GitHub for Windows

The installer includes a command line version of Git as well as the GUI. It also works well with Powershell, and sets up solid credential caching and sane CRLF settings. We’ll learn more about those things a little later, but suffice it to say they’re things you want. You can download this from the GitHub for Windows website, at http://windows.github.com.


GitHub config

On Windows systems, Git looks for the .gitconfig file in the $HOME directory (C:\Users\$USER for most people).

The first thing you should do when you install Git is to set your user name and email address. This is important because every Git commit uses this information, and it’s immutably baked into the commits you start creating:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

Configure editor

$ git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe'

Checking Your Settings

If you want to check your settings, you can use the git config --list command to list all the settings Git can find at that point

$ git config --list

Getting Help

If you ever need help while using Git, there are three ways to get the manual page (manpage) help for any of the Git commands:

$ git help 
$ git  --help
$ man git-

Initializing a Repository in an Existing Directory

If you’re starting to track an existing project in Git, you need to go to the project’s directory. If you’ve never done this, it looks a little different depending on which system you’re running:


for Windows:

$ cd /c/user/your_repository
$ git init

This creates a new subdirectory named .git that contains all of your necessary repository files – a Git repository skeleton. At this point, nothing in your project is tracked yet.

If you want to start version-controlling existing files (as opposed to an empty directory), you should probably begin tracking those files and do an initial commit. You can accomplish that with a few git add commands that specify the files you want to track, followed by a git commit:

$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version'

Cloning an Existing Repository

If you want to get a copy of an existing Git repository – for example, a project you’d like to contribute to – the command you need is git clone.

You clone a repository with git clone [url]. For example, if you want to clone the Git linkable library called libgit2, you can do so like this:

$ git clone https://github.com/libgit2/libgit2

That creates a directory named “libgit2”, initializes a .git directory inside it, pulls down all the data for that repository, and checks out a working copy of the latest version.

If you want to clone the repository into a directory named something other than “libgit2”, you can specify that as the next command-line option:

$ git clone https://github.com/libgit2/libgit2 mylibgit

That command does the same thing as the previous one, but the target directory is called mylibgit.

Git has a number of different transfer protocols you can use. The previous example uses the https:// protocol, but you may also see git:// or user@server:path/to/repo.git, which uses the SSH transfer protocol.

Checking the Status of Your Files

The main tool you use to determine which files are in which state is the git status command.

> git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working tree clean

Tracking New Files

In order to begin tracking a new file, you use the command git add. To begin tracking the README file, you can run this:

$ git add README

Staging Modified Files

Let’s change a file that was already tracked. If you change a previously tracked file called CONTRIBUTING.md and then run your git status command again, you get something that looks like this:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD ..." to unstage)


    new file:   README


Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)


    modified:   CONTRIBUTING.md

To stage it, you run the git add command. git add is a multipurpose command – you use it to begin tracking new files, to stage files, and to do other things like marking merge-conflicted files as resolved. It may be helpful to think of it more as “add this content to the next commit” rather than “add this file to the project”. Let’s run git add now to stage the CONTRIBUTING.md file, and then run git status again:

$ git add CONTRIBUTING.md
$ git status

Short Status

While the git status output is pretty comprehensive, it’s also quite wordy. Git also has a short status flag so you can see your changes in a more compact way. If you run git status -s or git status --short you get a far more simplified output from the command:

$ git status -s

 

Ignoring Files

Often, you’ll have a class of files that you don’t want Git to automatically add or even show you as being untracked. These are generally automatically generated files such as log files or files produced by your build system. In such cases, you can create a file listing patterns to match them named .gitignore. Here is an example .gitignore file:

$ cat .gitignore
*.[oa]

Viewing Your Staged and Unstaged Changes

If the git status command is too vague for you – you want to know exactly what you changed, not just which files were changed – you can use the git diff command.

To see what you’ve changed but not yet staged, type git diff with no other arguments:

$ git diff

Now you can use git diff to see what is still unstaged:

$ git diff

and git diff --cached to see what you’ve staged so far (--staged and --cached are synonyms):

$ git diff --cached

Committing Your Changes

Now that your staging area is set up the way you want it, you can commit your changes. Remember that anything that is still unstaged – any files you have created or modified that you haven’t run git add on since you edited them – won’t go into this commit. They will stay as modified files on your disk. In this case, let’s say that the last time you ran git status, you saw that everything was staged, so you’re ready to commit your changes. The simplest way to commit is to type git commit:

$ git commit

Doing so launches your editor of choice to enter commit comment.

Alternatively, you can type your commit message inline with the commit command by specifying it after a -m flag, like this:

$ git commit -m "Story 182: Fix benchmarks for speed"

Skipping the Staging Area

Although it can be amazingly useful for crafting commits exactly how you want them, the staging area is sometimes a bit more complex than you need in your workflow. If you want to skip the staging area, Git provides a simple shortcut. Adding the -a option to the git commit command makes Git automatically stage every file that is already tracked before doing the commit, letting you skip the git add part:

$ git commit -a -m 'added new benchmarks'

Removing Files

To remove a file from Git, you have to remove it from your tracked files (more accurately, remove it from your staging area) and then commit. The git rm command does that, and also removes the file from your working directory so you don’t see it as an untracked file the next time around.

If you simply remove the file from your working directory, it shows up under the “Changed but not updated” (that is, unstaged) area of your git status output:

$ rm PROJECTS.md
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
  (use "git add/rm ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)


        deleted:    PROJECTS.md


no changes added to commit (use "git add" and/or "git commit -a")

Then, if you run git rm, it stages the file’s removal:

$ git rm PROJECTS.md

Another useful thing you may want to do is to keep the file in your working tree but remove it from your staging area. In other words, you may want to keep the file on your hard drive but not have Git track it anymore. This is particularly useful if you forgot to add something to your .gitignore file and accidentally staged it, like a large log file or a bunch of .a compiled files. To do this, use the --cached option:

$ git rm --cached README

You can pass files, directories, and file-glob patterns to the git rm command. That means you can do things such as:

$ git rm log/\*.log

Note the backslash (\) in front of the *. This is necessary because Git does its own filename expansion in addition to your shell’s filename expansion. This command removes all files that have the .log extension in the log/ directory. Or, you can do something like this:

$ git rm \*~

This command removes all files whose names end with a ~.

Moving Files

Unlike many other VCS systems, Git doesn’t explicitly track file movement. If you rename a file in Git, no metadata is stored in Git that tells it you renamed the file. However, Git is pretty smart about figuring that out after the fact – we’ll deal with detecting file movement a bit later.

Thus it’s a bit confusing that Git has a mv command. If you want to rename a file in Git, you can run something like:

$ git mv file_from file_to

and it works fine. In fact, if you run something like this and look at the status, you’ll see that Git considers it a renamed file:

$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD ..." to unstage)


    renamed:    README.md -> README

However, this is equivalent to running something like this:

$ mv README.md README
$ git rm README.md
$ git add README

Viewing the Commit History

After you have created several commits, or if you have cloned a repository with an existing commit history, you’ll probably want to look back to see what has happened. The most basic and powerful tool to do this is the git log command.

$ git log

One of the more helpful options is -p, which shows the difference introduced in each commit. You can also use -2, which limits the output to only the last two entries:

$ git log -p -2

If you want to see some abbreviated stats for each commit, you can use the --stat option:

$ git log –stat

The oneline option prints each commit on a single line, which is useful if you’re looking at a lot of commits. In addition, the short, full, and fuller options show the output in roughly the same format but with less or more information, respectively:

$ git log –-pretty=oneline

Useful options for git log --pretty=format lists some of the more useful options that format takes.

The oneline and format options are particularly useful with another log option called --graph. This option adds a nice little ASCII graph showing your branch and merge history:

$ git log --graph --pretty=format:"%h %s" 

Limiting Log Output

In addition to output-formatting options, git log takes a number of useful limiting options – that is, options that let you show only a subset of commits.

However, the time-limiting options such as --since and --until are very useful. For example, this command gets the list of commits made in the last two weeks:

$ git log --since=2.weeks

Undoing Things

At any stage, you may want to undo something. Here, we’ll review a few basic tools for undoing changes that you’ve made. Be careful, because you can’t always undo some of these undos. This is one of the few areas in Git where you may lose some work if you do it wrong.

One of the common undos takes place when you commit too early and possibly forget to add some files, or you mess up your commit message. If you want to try that commit again, you can run commit with the --amend option:

$ git commit --amend

Unstaging a Staged File

The next two sections demonstrate how to work with your staging area and working directory changes.

$ git add *
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD ..." to unstage)


    renamed:    README.md -> README
    modified:   CONTRIBUTING.md

Right below the “Changes to be committed” text, it says use git reset HEAD ... to unstage. So, let’s use that advice to unstage the CONTRIBUTING.md file:

$ git reset HEAD CONTRIBUTING.md

Unmodifying a Modified File

What if you realize that you don’t want to keep your changes to the CONTRIBUTING.md file? How can you easily unmodify it – revert it back to what it looked like when you last committed (or initially cloned, or however you got it into your working directory)? Luckily, git status tells you how to do that, too. In the last example output, the unstaged area looks like this:

Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)


    modified:   CONTRIBUTING.md

It tells you pretty explicitly how to discard the changes you’ve made. Let’s do what it says:

$ git checkout -- CONTRIBUTING.md
$ git status

Showing Your Remotes

To see which remote servers you have configured, you can run the git remote command.

$ git remote

You can also specify -v, which shows you the URLs that Git has stored for the shortname to be used when reading and writing to that remote:

$ git remote -v

Adding Remote Repositories

We’ve mentioned and given some demonstrations of how the clone command implicitly adds the origin remote for you. Here’s how to add a new remote explicitly. To add a new remote Git repository as a shortname you can reference easily, run git remote add :

$ git remote
$ git remote add pb https://github.com/

Now you can use the string pb on the command line in lieu of the whole URL. For example, if you want to fetch all the information that Paul has but that you don’t yet have in your repository, you can run git fetch pb:

$ git fetch pb

Fetching and Pulling from Your Remotes

As you just saw, to get data from your remote projects, you can run:

$ git fetch [remote-name]

It’s important to note that the git fetch command only downloads the data to your local repository – it doesn’t automatically merge it with any of your work or modify what you’re currently working on. You have to merge it manually into your work when you’re ready.

If your current branch is set up to track a remote branch (see the next section and Git Branching for more information), you can use the git pull command to automatically fetch and then merge that remote branch into your current branch.

Pushing to Your Remotes

When you have your project at a point that you want to share, you have to push it upstream. The command for this is simple: git push [remote-name] [branch-name]. If you want to push your master branch to your origin server (again, cloning generally sets up both of those names for you automatically), then you can run this to push any commits you’ve done back up to the server:

$ git push origin master

Inspecting a Remote

If you want to see more information about a particular remote, you can use the git remote show [remote-name] command. If you run this command with a particular shortname, such as origin, you get something like this:

$ git remote show origin

Removing and Renaming Remotes

You can run git remote rename to change a remote’s shortname. For instance, if you want to rename pb to paul, you can do so with git remote rename:

$ git remote rename pb paul
$ git remote
origin
paul

It’s worth mentioning that this changes all your remote-tracking branch names, too. What used to be referenced at pb/master is now at paul/master.

If you want to remove a remote for some reason – you’ve moved the server or are no longer using a particular mirror, or perhaps a contributor isn’t contributing anymore – you can either use git remote remove or git remote rm:

$ git remote remove paul
$ git remote
origin

Tagging

Like most VCSs, Git has the ability to tag specific points in history as being important. Typically people use this functionality to mark release points (v1.0, and so on). In this section, you’ll learn how to list the available tags, how to create new tags, and what the different types of tags are.

Listing the available tags in Git is straightforward. Just type git tag:

$ git tag

Creating Tags

Git uses two main types of tags: lightweight and annotated.

A lightweight tag is very much like a branch that doesn’t change – it’s just a pointer to a specific commit.

Annotated tags, however, are stored as full objects in the Git database.

Annotated Tags

Creating an annotated tag in Git is simple. The easiest way is to specify -a when you run the tag command:

$ git tag -a v1.4 -m "my version 1.4"
$ git tag
v0.1
v1.3
v1.4

The -m specifies a tagging message, which is stored with the tag. If you don’t specify a message for an annotated tag, Git launches your editor so you can type it in.

You can see the tag data along with the commit that was tagged by using the git show command:

$ git show v1.4

That shows the tagger information, the date the commit was tagged, and the annotation message before showing the commit information.

Lightweight Tags

Another way to tag commits is with a lightweight tag. This is basically the commit checksum stored in a file – no other information is kept. To create a lightweight tag, don’t supply the -a, -s, or -m option:

$ git tag v1.4-lw
$ git tag
v0.1
v1.3
v1.4
v1.4-lw
v1.5

This time, if you run git show on the tag, you don’t see the extra tag information. The command just shows the commit:

$ git show v1.4-lw
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon
Date:   Mon Mar 17 21:52:11 2008 -0700


    changed the version number

Tagging Later

You can also tag commits after you’ve moved past them. Suppose your commit history looks like this:

$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme

Now, suppose you forgot to tag the project at v1.2, which was at the “updated rakefile” commit. You can add it after the fact. To tag that commit, you specify the commit checksum (or part of it) at the end of the command:

$ git tag -a v1.2 9fceb02

Sharing Tags

By default, the git push command doesn’t transfer tags to remote servers. You will have to explicitly push tags to a shared server after you have created them. This process is just like sharing remote branches – you can run git push origin [tagname].

$ git push origin v1.5

If you have a lot of tags that you want to push up at once, you can also use the --tags option to the git push command. This will transfer all of your tags to the remote server that are not already there.

$ git push origin --tags

Now, when someone else clones or pulls from your repository, they will get all your tags as well.

Checking out Tags

You can’t really check out a tag in Git, since they can’t be moved around. If you want to put a version of your repository in your working directory that looks like a specific tag, you can create a new branch at a specific tag with git checkout -b [branchname] [tagname]:

$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'

Of course if you do this and do a commit, your version2 branch will be slightly different than your v2.0.0 tag since it will move forward with your new changes, so do be careful.

Git branching

Use the branch command with a name to create a new branch with that name.

$ git branch
* develop
  master

Use -a flag to check also remote branches

git branch -a
* develop
  master
  remotes/origin/develop
  remotes/origin/master

Add a new branch

$ git branch new_issue


$ git branch
* develop
  master
  new_issue


$ git branch -a
* develop
  master
  new_issue
  remotes/origin/develop
  remotes/origin/master

Switch branches

Switch over to the branch "new_issue" when you want to add new commits to it.

Use the checkout command to switch branch.

$ git checkout new_issue
Switched to branch 'new_issue'

By passing in the -b option when executing the checkout command, a new branch will be created and you will be switched over after that. 

$ git checkout -b new_issue2
Switched to a new branch 'new_issue2'

If the branch already exists, an error is raised

$ git checkout -b new_issue
fatal: A branch named 'new_issue' already exists.

Once you are on the "new_issue" branch, you can start adding commits to it. 

Create a new file new_issue_file.txt

$ git status
On branch new_issue
Untracked files:
  (use "git add ..." to include in what will be committed)


        new_issue_file.txt


nothing added to commit but untracked files present (use "git add" to track)
$ git add new_issue_file.txt

$ git status
On branch new_issue
Changes to be committed:
  (use "git reset HEAD ..." to unstage)


        new file:   new_issue_file.txt
$ git commit -m "Add new_issue_file"
[new_issue2 57736d7] Add new_issue_file
 1 file changed, 2 insertions(+)
 create mode 100644 D8/scripts/asm/new_issue_file.txt


Git tree

$ git log --graph --oneline --all
* 57736d7 (HEAD -> new_issue2) Add new_issue2_file
* 49ce8cf (origin/develop, new_issue, develop) Add asm scripts
* 2e5c8a2 Rename ReadMe.txt
*   c601f03 Merge remote-tracking branch 'origin/develop' into develop
|\
| | *   a6abcee (origin/master, master) Merge remote-tracking branch 'origin/master'
| | |\
| |/ /
|/| /
| |/
| * 92c2dbc Create ReadMe.txt
* 07665d1 initial commit

Merge branches

Use the merge command to merge branches.

$ git merge 

By running the command above, the specified commit will be merged to the current active branch. 

$ git checkout master
Already on 'master'
Your branch is ahead of 'origin/master' by 4 commits.
  (use "git push" to publish your local commits)


$ git merge new_issue2
Merge made by the 'recursive' strategy.
 D8/scripts/asm/new_issue2_file.txt | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 D8/scripts/asm/new_issue2_file.txt

Git tree

$ git log --graph --oneline --all
*   59814f0 (HEAD -> master) Merge branch 'new_issue2'
|\
| * 57736d7 (new_issue2) Add new_issue2_file
* |   6225a13 Merge branch 'new_issue'
|\ \
| |/
...

Delete branch

Now that "new_issue2" has been successfully merged with "master", we can delete it.

We can delete a branch by calling the branch command and passing in the -d option, followed by the branch name.

$ git branch -d 
$ git branch -d new_issue2
Deleted branch new_issue2 (was 57736d7).
$ git branch
  develop
* master

Work in parallel

Branching allows us to work in multiple parallel workspaces.

Let's create two branches. Create one with the name "new_issue2" and another with the name"new_issue3", then switch over to "new_issue2".

$ git branch new_issue2
$ git branch new_issue3
$ git checkout new_issue2
Switched to branch 'new_issue2'
$ git branch
  develop
  master
* new_issue2
  new_issue3

Add the bold text below to new_issue2_file.txt and commit the change. 

Git commands even a monkey can understand
add: Register a change in an indexcommit: Save the index status


$ git status
On branch new_issue2
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git checkout -- ..." to discard changes in working directory)


        modified:   new_issue2_file.txtno changes added to commit (use "git add" and/or "git commit -a")
$ git add new_issue2_file.txt
$ git commit -m "Save the index status"
[new_issue2 2c4d9bc] Save the index status
 1 file changed, 2 insertions(+), 1 deletion(-)

A fast-forward merge (Git simply moves the commit pointer forward) has now been executed.

Now switch to "new_issue3" branch. 

$ git checkout new_issue3
Switched to branch 'new_issue3'

"new_issue3" currently has the same history/content as the master branch. It will not include the recent change that we have just made. This is because the recent change has been commited to the "new_issue2" branch.

Add the bold text below to new_issue2_file.txt and commit the change. 

Git commands even a monkey can understand
add: Register a change in an indexpull: Get remote content
$ git add new_issue2_file.txt
$ git commit -m "Get remote content"
[new_issue3 58c5f07] Get remote content
 1 file changed, 2 insertions(+), 1 deletion(-)

Resolve a merge conflict

Now let's merge branches "new_issue2" and "new_issue3" into the master branch.

We will switch over to "master" and merge "new_issue2" with it and then "new_issue3"

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
  (use "git push" to publish your local commits)

$ git merge new_issue2
Updating 59814f0..2c4d9bc
Fast-forward
 D8/scripts/asm/new_issue2_file.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

$ git merge new_issue3
Auto-merging D8/scripts/asm/new_issue2_file.txt
CONFLICT (content): Merge conflict in D8/scripts/asm/new_issue2_file.txt
Automatic merge failed; fix conflicts and then commit the result.

Git has identified a conflict and will not allow you to automatically merge "new_issue3" with "master". The conflict here pertains to the same line on new_issue2_file.txtt with different content on both branches. Due to the conflict during the attempt to merge, new_issue2_file.txt will look something like this.

Git commands even a monkey can understand
add: Register a change in an index
<<<<<<< HEAD
commit: Save the index status
=======
pull: Get remote content
>>>>>>> new_issue3

Update the file like this

Git commands even a monkey can understand
add: Register a change in an index
commit: Save the index status
pull: Get remote content


$ git status
On branch master
Your branch is ahead of 'origin/master' by 7 commits.
  (use "git push" to publish your local commits)


You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)


Unmerged paths:
  (use "git add ..." to mark resolution)


        both modified:   new_issue2_file.txt


no changes added to commit (use "git add" and/or "git commit -a")
$ git add new_issue2_file.txt
$ git commit -m "new_issue3 branch merge"
[master d143a7b] new_issue3 branch merge

Git tree

The revision history will now look like the one below. A new merge commit has been created as a result of the conflict resolution. The master branch is now pointing to the latest merge commit. 

This is a non fast-forward merge.

$ git log --graph --oneline --all
*   d143a7b (HEAD -> master) new_issue3 branch merge
|\
| * 58c5f07 (new_issue3) Get remote content
* | 2c4d9bc (new_issue2) Save the index status
|/
*   59814f0 Merge branch 'new_issue2'

Rebase a branch

Another approach we can take to integrate "issue3" branch into the master branch is by using the rebase command. Using rebase, we can streamline and clean our history tree just like how we have described earlier.

Let's start by undoing the previous merge.

$ git reset --hard HEAD~
HEAD is now at 2c4d9bc Save the index status

$ git log --graph --oneline --all
* 58c5f07 (new_issue3) Get remote content
| * 2c4d9bc (HEAD -> master, new_issue2) Save the index status
|/
*   59814f0 Merge branch 'new_issue2'

Switch over to "new_issue3" branch and rebase onto the master branch. 

$ git checkout new_issue3
Switched to branch 'new_issue3'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Get remote content
Using index info to reconstruct a base tree...
M       D8/scripts/asm/new_issue2_file.txt
Falling back to patching base and 3-way merge...
Auto-merging D8/scripts/asm/new_issue2_file.txt
CONFLICT (content): Merge conflict in D8/scripts/asm/new_issue2_file.txt
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch' to see the failed patch
Patch failed at 0001 Get remote content


Resolve all conflicts manually, mark them as resolved with
"git add/rm ", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

When a conflict occurs during the rebase, you will have to resolve it immediately in order to resume the rebase operation. 

Git commands even a monkey can understand
add: Register a change in an index
<<<<<<< HEAD
commit: Save the index status
=======
pull: Get remote content
>>>>>>> Get remote content


$ git status
rebase in progress; onto 2c4d9bc
You are currently rebasing branch 'new_issue3' on '2c4d9bc'.
  (fix conflicts and then run "git rebase --continue")
  (use "git rebase --skip" to skip this patch)
  (use "git rebase --abort" to check out the original branch)

Unmerged paths:
  (use "git reset HEAD ..." to unstage)
  (use "git add ..." to mark resolution)

        both modified:   new_issue2_file.txt

no changes added to commit (use "git add" and/or "git commit -a")

$ git add new_issue2_file.txt
$ git rebase --continue

With the "new_issue3" branch rebased onto "master", we can now issue a fast-forward merge.

Switch over to the master branch and merge "new_issue3" with "master".

$ git status
On branch new_issue3
nothing to commit, working tree clean

$ git log --graph --oneline --all
* 48c3600 (HEAD -> new_issue3) Get remote content
* 2c4d9bc (new_issue2, master) Save the index status
*   59814f0 Merge branch 'new_issue2'
|\
| * 57736d7 Add new_issue2_file
* |   6225a13 Merge branch 'new_issue'
...

$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 7 commits.
  (use "git push" to publish your local commits)


$ git merge new_issue3
Updating 2c4d9bc..48c3600
Fast-forward
 D8/scripts/asm/new_issue2_file.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)


$ git log --graph --oneline --all
* 48c3600 (HEAD -> master, new_issue3) Get remote content
* 2c4d9bc (new_issue2) Save the index status
*   59814f0 Merge branch 'new_issue2'
|\
| * 57736d7 Add new_issue2_file
* |   6225a13 Merge branch 'new_issue'
...



Comments
* The email will not be published on the website.