$ mkdir test
$ cd test
$ git init
Initialised empty Git repository in /home/bojan/dev/test/.git/
Initialised empty Git repository in /home/bojan/dev/test/.git/
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
$ touch foo.txt
$ vi foo.txt
foo.txt:
feature A {
A.1
A.2
A.3
}
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
foo.txt
nothing added to commit but untracked files present (use "git add" to track)
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
foo.txt
nothing added to commit but untracked files present (use "git add" to track)
$ git add foo.txt
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: foo.txt
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: foo.txt
$ git commit -m "Added feature A"
[master (root-commit) ae68f9e] Added feature A
1 file changed, 5 insertions(+)
create mode 100644 foo.txt
[master (root-commit) ae68f9e] Added feature A
1 file changed, 5 insertions(+)
create mode 100644 foo.txt
Let's now create a feature branch for feature B. Let's assume we add a bug in its first implementation.
$ git checkout -b feature/B
Switched to a new branch 'feature/B'
Switched to a new branch 'feature/B'
$ vi foo.txt
foo.txt:
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug
B.3
}
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug
B.3
}
$ git status
On branch feature/B
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: foo.txt
no changes added to commit (use "git add" and/or "git commit -a")
On branch feature/B
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: foo.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git add foo.txt
$ cat foo.txt
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug
B.3
}
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug
B.3
}
$ git commit -m "Added feature B"
[feature/B c2f2c7d] Added feature B
1 file changed, 6 insertions(+)
[feature/B c2f2c7d] Added feature B
1 file changed, 6 insertions(+)
$ git log
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (HEAD -> feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e (master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (HEAD -> feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e (master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
$ git rebase master
Current branch feature/B is up to date.
Current branch feature/B is up to date.
$ git checkout master
Switched to branch 'master'
Switched to branch 'master'
$ git merge feature/B
Updating ae68f9e..c2f2c7d
Fast-forward
foo.txt | 6 ++++++
1 file changed, 6 insertions(+)
Updating ae68f9e..c2f2c7d
Fast-forward
foo.txt | 6 ++++++
1 file changed, 6 insertions(+)
Let's assume we've now realized that there's a bug in the current implementation of feature B.
$ git log
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (HEAD -> master, feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (HEAD -> master, feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
$ git revert c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d
[master cd72121] Revert "Added feature B"
1 file changed, 6 deletions(-)
[master cd72121] Revert "Added feature B"
1 file changed, 6 deletions(-)
$ git log
commit cd721217e154dc74cad4037135c0ea2c0b898696 (HEAD -> master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:42:57 2022 +0100
Revert "Added feature B"
This reverts commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d.
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
commit cd721217e154dc74cad4037135c0ea2c0b898696 (HEAD -> master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:42:57 2022 +0100
Revert "Added feature B"
This reverts commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d.
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
We now want to fix the bug so we create a new branch, B2, by branching off feature/B:
$ git checkout feature/B
Switched to branch 'feature/B'
Switched to branch 'feature/B'
$ git checkout -b feature/B2
Switched to a new branch 'feature/B2'
Switched to a new branch 'feature/B2'
$ cat foo.txt
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug
B.3
}
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug
B.3
}
$ vi foo.txt
foo.txt:
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug fixed
B.3
}
$ git status
On branch feature/B2
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: foo.txt
no changes added to commit (use "git add" and/or "git commit -a")
On branch feature/B2
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: foo.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git commit -a -m "Fixed bug in feature B"
[feature/B2 29dbed4] Fixed bug in feature B
1 file changed, 1 insertion(+), 1 deletion(-)
[feature/B2 29dbed4] Fixed bug in feature B
1 file changed, 1 insertion(+), 1 deletion(-)
$ git status
On branch feature/B2
nothing to commit, working tree clean
On branch feature/B2
nothing to commit, working tree clean
$ cat foo.txt
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug fixed
B.3
}
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug fixed
B.3
}
Before we merge feature branch to trunk, we first want to rebase it:
$ git rebase -i master
Auto-merging foo.txt
CONFLICT (content): Merge conflict in foo.txt
error: could not apply 29dbed4... Fixed bug in feature B
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", 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".
Could not apply 29dbed4... Fixed bug in feature B
Auto-merging foo.txt
CONFLICT (content): Merge conflict in foo.txt
error: could not apply 29dbed4... Fixed bug in feature B
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", 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".
Could not apply 29dbed4... Fixed bug in feature B
$ vi foo.txt
We're taking all changes from feature branch.
$ git add foo.txt
$ git rebase --continue
[detached HEAD b86cff8] Fixed bug in feature B
1 file changed, 7 insertions(+)
Successfully rebased and updated refs/heads/feature/B2.
[detached HEAD b86cff8] Fixed bug in feature B
1 file changed, 7 insertions(+)
Successfully rebased and updated refs/heads/feature/B2.
$ git log
commit b86cff82118bb6af2bf10a4adf584e924acaaed0 (HEAD -> feature/B2)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:47:55 2022 +0100
Fixed bug in feature B
commit cd721217e154dc74cad4037135c0ea2c0b898696 (master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:42:57 2022 +0100
Revert "Added feature B"
This reverts commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d.
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
commit b86cff82118bb6af2bf10a4adf584e924acaaed0 (HEAD -> feature/B2)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:47:55 2022 +0100
Fixed bug in feature B
commit cd721217e154dc74cad4037135c0ea2c0b898696 (master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:42:57 2022 +0100
Revert "Added feature B"
This reverts commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d.
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
$ git status
On branch feature/B2
nothing to commit, working tree clean
On branch feature/B2
nothing to commit, working tree clean
We can now merge feature branch into master:
$ git checkout master
Switched to branch 'master'
Switched to branch 'master'
$ git status
On branch master
nothing to commit, working tree clean
On branch master
nothing to commit, working tree clean
$ git log
commit cd721217e154dc74cad4037135c0ea2c0b898696 (HEAD -> master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:42:57 2022 +0100
Revert "Added feature B"
This reverts commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d.
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
commit cd721217e154dc74cad4037135c0ea2c0b898696 (HEAD -> master)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:42:57 2022 +0100
Revert "Added feature B"
This reverts commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d.
commit c2f2c7d39fb93b3fb45ec9ff384e0ebd5303253d (feature/B)
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:36:48 2022 +0100
Added feature B
commit ae68f9ea4bf55f54a8f40831df5b980dc30e5c6e
Author: Bojan Komazec <bojan.komazec@example.com>
Date: Mon Aug 8 21:34:20 2022 +0100
Added feature A
$ git merge feature/B2
Updating cd72121..b86cff8
Fast-forward
foo.txt | 7 +++++++
1 file changed, 7 insertions(+)
Updating cd72121..b86cff8
Fast-forward
foo.txt | 7 +++++++
1 file changed, 7 insertions(+)
$ git status
On branch master
nothing to commit, working tree clean
On branch master
nothing to commit, working tree clean
$ cat foo.txt
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug fixed
B.3
}
feature A {
A.1
A.2
A.3
}
feature B {
B.1
B.2 - bug fixed
B.3
}
We assumed here that we had the original feature branch available. Alternatively, we could have created a new branch off the master, reverse the reverse commit, apply the fix and then merge it back to master.