git --amend
Asked by Sandeep Anand:

Hi,

Can anyone help me in my quest in sourcetree?

I am trying to produce the problem that one can have if he uses git --amend to amend an already pushed commit. I know the concept of the problem that can occur by this. But I want to produce it to demonstrate to my developers and create a little user guide for them on how to effectively use git --amend command.

I am not able to see what problem can occur if we amend a pushed commit.

What I am trying to do is:

1) Create a master repository,

2) Then clone it at two different places.

3) At one clone I make some changes and then commit them. Push them.

4) At another clone, I pull those changes, create a branch based on them and commit them. But do not push them.

5) Now back at clone one, I make some more changes and commit them with amend option and replace the recent commit that had already been pushed.

6) It does give me those two warning popup messages but I proceed through.

7) After that I go the clone2 and pull the changes, which come through. Now here I should see some problems, right? but I do not. so what issue has git --amend caused here?

Regards

Sandeep Anand


Answers:
author: Sandeep Anand
body: yes, I am going to implement that after exlaining it my build manager.


author: Sandeep Anand
body: great!

thanks for all the information, Balazs.....

i am absolutely new to Git, stash and sourcetree. so doing lot of R\&D to understand them.

thanks again.

comments: author: Bal?zs Szakm?ry
body: You're welcome. If everybody involved is new to Git, I would definitely recommend rejecting force pushes, to limit the possible damage due mistakes.


author: Sandeep Anand
body: And, I think in sourcetree there is no option to push -force.

so if a developer pull from remote and merge it in his local repository before pushing his amended commit, then nothing gets lost. right?

then i can just put some wrapper around, in the server that no push --force should be accepted.

comments: author: Bal?zs Szakm?ry
body: Yes.

The "Reject Force Push" functionality is a hook that can be enabled/disabled in the hooks section of the settings of each repository.


author: Bal?zs Szakm?ry
body: 0: Yes

1.: If the commit was pushed before, you always need to force push the amended version. You can do that without pulling first.

2.: When you replace the old commit with the new one, the way that happens is that the old one is \*deleted\* and a new one is created. Thus the original parent references pointing to the old one become invalid (and they probably get cleaned up, so the child commits becomes orphans and then they probably get rebased to the new one if the graph has not changed too much.)

The commits of the other devs referencing the changed commit do not disappear, but they do become unreachable in the graph (which probably gets auto-corrected afterwards, see above).

3.: This all first happens on the server, but later gets synchronised to the others (they need to pull this change first before they can push anything on top of it, unless they themselves are force-pushing stuff which will again rewrite the history to yet another alternate version.)


author: Sandeep Anand
body: thanks again, balazs.

just reading the link you suggested....

you say "Personally, I think that history already pushed to the server (and pulled by others) should never be changed." so it means that git comment --amend can do that blunder, right?

but how can I demonstrate it in sourcetree (if it is possible). my observations are as follows:

1) First, in sourcetree one cannot push an amended commit at all. Which means if I want to push an amended commit which had already been pushed in last attempt, I have no option but to first pull from the remote branch in my local repository. And, by this it makes sure that previous commit is not lost. It stays there.

2) Second, if I do want to push an amended commit without pulling first, I have to use **git push --force**command. For which I will have to open git bash terminal as --force option is not available in sourcetree. In this case, it will go ahead and replace the previously pushed commit on the remote server. But even now, I don't see any issue because if any second developer had already pulled the previous commit (before amend) to his local and started working on it (changed, or created a new branch etc.) or even not changed it and, then pull the newer commit from remote, his changes are not lost. He will have to merge it and his previous history remains intact. The earlier commit on which his changes are based are still there.

3) Moreover, after he has merged it and now pushes his changes to remote, the commit which was replaced by the first user appears back.

I am not able to find what are we losing here. **git amend** command is replacing the recent commits only till the distance of remote server (and that too if used git push --force from git bash) but does not extend the replacement to other developers.

sorry, if I am putting silly queries here...

<br />

<br />


author: Bal?zs Szakm?ry
body: Already pushed and then amended commits can only be force-pushed. There is a built-in commit hook in Stash to automatically reject force pushes, I highly recommend using it. (History can be messed up in much more serious ways by force pushes, e.g. by pushing a completely empty repository with no history of anything.)

Personally, I think that history already pushed to the server (and pulled by others) should never be changed. Whenever you can amend a commit, you can also simply push another one on top of it. All other mistakes can be rectified by reverting commits and redoing them correctly. It is important that everybody can follow what happened, including the mistakes. At the end of the day, the thing that really matters is that the latest version of the code is OK.

In my opinion, having good-looking history is less important than having "correct" history. It might very well be that this (at least in the case of amends) is more of a philosophical issue than a practical one. I found [this](http://paul.stadig.name/2010/12/thou-shalt-not-lie-git-rebase-ammend.html), interesting reading. The only objectively bad thing the guy says about amend is "It breaks ```git branch --contains some-branch```".


author: Sandeep Anand
body: Hi Balazs, thanks for your response.

the problem is that no matter how much I try I am not able to lose any commit on remote by pushing an amended commit. It some how seems that sourcetree does not allow to push an amended commit directly. I can do that by using push --force from git bash. But even then if other developer who had already pulled the original commit, tries to pull the amended commit, he has to merge it first. which retains all his previous commits and history.

so just wondering what are we losing and even if something is getting lost at back like you said about SHA-1 hash, how can that cause any issue?

I seeking this so that I can further educate my users on how to use --amend with care.

since we are rolling out sourcetree to be used as official git front end GUI in our production environment, my scope is within sourctree only.


author: Bal?zs Szakm?ry
body: Amend changes the SHA-1 hash of the commit you are amending. If this commit is a basis of another branch, the parent pointer of the first commit in the other branch becaomes invalid and the branch becomes an orphan.

Most probably, in the simple example above, git figures out the change in the background and automatically rebases your branch so that the first commit points to the amended version of its parent.

I would not count on this always working correctly in a production environment with many branches and many people pushing changes.


Tags: bitbucket-server

git

push