yusuf
yusuf

Reputation: 3781

Modifying a gitlab commit

I would like to modify a git commit which I pushed long time ago. Is there any simple and straightforward way to do that?

I have made a lot of changes since then, and it is very confusing and risky for me to do it with git rebase.

I can still use git rebase but I am very new for git usage.

The commit involves the first file of my repository, and I am not allowed to create a new commit for changing a file which I pushed with my first commit.

Upvotes: 0

Views: 616

Answers (2)

matt
matt

Reputation: 536027

Now that you've granted that we are allowed to make new commits to achieve the desired effect, the easy way to do this is: Do what it says at How to inject a commit between some two arbitrary commits in the past? to insert the change commit after the problem commit. Then interactive rebase to squash the inserted commit to the problem commit.

I'll demonstrate:

humlet:gittest matt$ git init
humlet:gittest matt$ echo test > dummy.txt
humlet:gittest matt$ git add .
humlet:gittest matt$ git commit -m "start"
humlet:gittest matt$ echo crucial > crucial.txt
humlet:gittest matt$ git add .
humlet:gittest matt$ git commit -m "created crucial file"
humlet:gittest matt$ echo test2 > dummy.txt
humlet:gittest matt$ git commit -am "changed dummy"
humlet:gittest matt$ echo test3 > dummy.txt
humlet:gittest matt$ git commit -am "changed dummy again"

git log shows that the commits are

    changed dummy again
    changed dummy
    created crucial file
    start

Okay, so the goal is to change what is in crucial.txt and put that commit in place of the "created crucial file" commit. git log shows that that commit is 785f75. Here we go:

humlet:gittest matt$ git branch temp 785f75
humlet:gittest matt$ git checkout temp
humlet:gittest matt$ echo whoa > crucial.txt
humlet:gittest matt$ git commit -am "teehee"
humlet:gittest matt$ git rebase temp master

We've now inserted a commit ("teehee") containing the revised crucial.txt, but we have one too many commits:

    changed dummy again
    changed dummy
    teehee
    created crucial file
    start

So now we go back and squash "teehee" onto "created crucial file". To do so, we do an interactive rebase starting at the commit preceding both of them, which is "start"; git log shows that that is e01e0c5:

humlet:gittest matt$ git rebase -i e01e0c5

In the interactive rebase, we pick all the commits we are shown, except that we squash "teehee". When we are offered a chance to revise the commit message, we change it to "created crucial file". git log shows that we now have

    changed dummy again
    changed dummy
    created crucial file
    start

Okay, now let's check what's in the "created crucial file" commit:

humlet:gittest matt$ git diff 65c198 e01e0c
diff --git a/crucial.txt b/crucial.txt
deleted file mode 100644
index 0a6a129..0000000
--- a/crucial.txt
+++ /dev/null
@@ -1 +0,0 @@
-whoa

So, you see, it looks like "created crucial file" added crucial.txt and it consisted of "whoa". That is the desired result.

Disclaimer: Changing history that you have pushed is wrong. Don't do it.

Upvotes: 0

VonC
VonC

Reputation: 1329692

What I want to do is, changing a specific file content,

Instead of an interactive rebase, use git filter-repo, which replaces BFG or filter-branch.

Use content filtering

At the end, you can (if you are the only one working on that repository) do a git push --force

If you want to modify file contents, you can do so based on a list of expressions in a file, one per line.
For example, with a file named expressions.txt containing:

p455w0rd
foo==>bar
glob:*666*==>
regex:\bdriver\b==>pilot
literal:MM/DD/YYYY=>YYYY-MM-DD
regex:([0-9]{2})/([0-9]{2})/([0-9]{4})==>\3-\1-\2

then running

git filter-repo --replace-text expressions.txt

will go through and replace:

  • p455w0rd with ***REMOVED***,
  • foo with bar,
  • any line containing 666 with a blank line,
  • the word driver with pilot (but not if it has letters before or after; e.g. drivers will be unmodified),
  • the exact text MM/DD/YYYY with YYYY-MM-DD and
  • date strings of the form MM/DD/YYYY with ones of the form YYYY-MM-DD.

Upvotes: 1

Related Questions