0

I have a situation where I need to inactivate a feature in a branch, make adjustments to it and then activate again on future.

My initial scenario:

$ git log
14c9dcd (HEAD -> master) feature 3
af64271 feature 2
da0507a feature 1
  • 14c9dcd -- created file3.txt
  • af64271 -- edited the file1.txt; created file2.txt
  • da0507a -- add the file1.txt

Now i need to revert the af64271 commit just on master branch and keep the code changes avaliable to get back ( with some changes ) later.

I tried to do:

$ git checkout -b save_feature_2
    $ git checkout master
    $ git log --oneline   
        14c9dcd (HEAD -> master, save_feature_2) feature 3
        af64271 feature 2
        da0507a feature 1

#Reverting the "feature 2" commit changes
$ git revert af64271
    [master 8fcee28] Revert "feature 2"
    2 files changed, 1 insertion(+), 2 deletions(-)
     delete mode 100644 file2.txt

# Checking the differences
$ git diff save_feature_2
    diff --git a/file1.txt b/file1.txt
    index ba36cc9..8e90503 100644
    --- a/file1.txt
    +++ b/file1.txt
    @@ -1,2 +1 @@
    -<somecode here>
    -<more code here>
    \ No newline at end of file
    +<somecode here>
    \ No newline at end of file
    diff --git a/file2.txt b/file2.txt
    deleted file mode 100644
    index e69de29..0000000

# Checking log on master
$ git log --oneline
    8fcee28 (HEAD -> master) Revert "feature 2"
    14c9dcd (save_feature_2) feature 3
    af64271 feature 2
    da0507a feature 1

# Checking the save_feature_2 log branch
$ git checkout save_feature_2
$ git log --oneline
    14c9dcd (HEAD -> save_feature_2) feature 3
    af64271 feature 2
    da0507a feature 1

# Making same improviments on "feature 2" addind some code just on "file3.txt"
$ git log --oneline
    c4ff7f2 (HEAD -> save_feature_2) improvements on feature 2
    14c9dcd feature 3
    af64271 feature 2
    da0507a feature 1

# Now i need to reactivate the "feature 2" on master
$ git checkout master
$ git diff save_feature_2
    diff --git a/file1.txt b/file1.txt
    index ba36cc9..8e90503 100644
    --- a/file1.txt
    +++ b/file1.txt
    @@ -1,2 +1 @@
    -<somecode here>
    -<more code here>
    \ No newline at end of file
    +<somecode here>
    \ No newline at end of file
    diff --git a/file2.txt b/file2.txt
    deleted file mode 100644
    index e69de29..0000000
    diff --git a/file3.txt b/file3.txt
    index f70ef26..e69de29 100644
    --- a/file3.txt
    +++ b/file3.txt
    @@ -1 +0,0 @@
    -<improvements on feature 2>
    \ No newline at end of file

$ git merge save_feature_2
    Merge made by the 'recursive' strategy.
     file3.txt | 1 +
     1 file changed, 1 insertion(+)

$ git log --oneline
b10eabc (HEAD -> master) Merge branch 'save_feature_2' - Reactivating the feature 2
c4ff7f2 (save_feature_2) improvements on feature 2
8fcee28 Revert "feature 2"
14c9dcd feature 3
af64271 feature 2
da0507a feature 1

# At this point the "file2.txt" was no merged!

$ ls (master)
file1.txt  file3.txt
$ git checkout save_feature_2
$ ls (save_feature_2)
file1.txt  file2.txt  file3.txt

As you can see the file2.txt was not merged!

Pablo Souza
  • 863
  • 2
  • 11
  • 25
  • 2
    I think [feature flags](https://www.martinfowler.com/articles/feature-toggles.html) would be a clearer way to do this. – crashmstr Apr 25 '19 at 13:38
  • For example, see https://stackoverflow.com/questions/7707383/what-is-a-feature-flag – Don Branson Apr 25 '19 at 13:39
  • `git revert` actually isn't a bad way to go here. Just revert the commit, or range of commits, which make up the feature you want to erase. Then, build your new feature on top, and finally do a rebase to excise the revert commits. Nothing wrong with rewriting history assuming all of this is happening locally. – Tim Biegeleisen Apr 25 '19 at 13:41
  • reverting a merge does not mean "remove the common ancestor" – OznOg Apr 25 '19 at 13:46

1 Answers1

0

The branch save_feature_2 should contain the revert commit and additionally the revert of the revert commit.

When you merge this branch back to master you'll get the feature activated again.

More specifically:

  1. Initially you have branch master with commit FEATURE (FEATURE is the hash of the feature commit).
  2. You want to revert FEATURE and create REVERT_OF_FEATURE on master branch (this is the hash of the commit generated by git revert FEATURE)
  3. You create a branch called FEATURE_BRANCH or whatever. (git co -b FEATURE_BRANCH) and on this new branch, you revert the revert commit (git revert REVERT_OF_FEATURE)
  4. You continue working on master (there the feature is not present now) and on FEATURE_BRANCH (Here the feature is present again and you can continue working on it)
  5. Finally you merge FEATURE_BRANCH back to master and you get the original feature and the additional changes on master.

The problem you had is because when merging branch save_feature_2 back to master, what happens is that the changes of all commits that are in save_feature_2 branch and are not already contained on target branch (master) are taken. But the original feature commit were already there, so those changes are not included. But if you include the revert commit and the revert of the revert commit on that feature branch you'll achieve what you want.

If you want to fix your current situation as it is, you can simply merge master in FEATURE_BRANCH (you'll get the REVERT_OF_FEATURE commit there) and then revert there the REVERT_OF_FEATURE commit.

Nevertheless, I find feature flags a nice thing, as @crashmstr already mentioned in comments.

Manuel Schmidt
  • 2,178
  • 2
  • 15
  • 19