Replace all existing files in git repository with a different remote branch except the ones in .gitignore

3.6k views Asked by At

I have several repositories that I always have to merge one core repository into. The core repository is setup as a remote repository in every repository.

Generally, my workflow to update repositories goes like this:

git reset --hard origin/master
git pull origin master
git fetch core master

I then do a git merge --squash core/master and fix any conflicts before pushing the repository back to remote.

This is fine, except it is a little redundant because aside from everything in the .gitignore file for each repository, everything in these repositories should technically be the same as the core repository.

As the number of repositories expand, I'm wondering what a more efficient way of pulling the core branch into these repositories would be given that I need to replace all existing files except the ones specifically mentioned in .gitignore for every one of them while maintaining integrity in git history and logs.

1

There are 1 answers

3
TheChetan On

You can do it with a combination of git and bash. I've written a sample script to show how it can be done. You can always modify it and make it better. I've provided some explanation also. This file is called adder.sh.

#!/bin/bash
# $1 -> Files from the branch you want (core)
# $2 -> Branch you want to merge into (master)

git checkout $2
git diff --name-status $1..$2 | grep '^\(D\|M\)\s*' | cut -f2 > ~/.dummy
git checkout $1 -- $(cat ~/.dummy)
git add .

To invoke it, just use $ sh adder.sh core master. After this all newly added and modified files from the core branch will be added to the master repo. With a git status you can see what's new, then commit and push accordingly.

$ git commit -m "Skipping Conflicts"
$ git push

Some explanation to how it works:

$ git diff --name-status master..core

Produces the following output:

M       public/stylesheets/main.css              # Modified
D       public/templates/createUser.html         # Present in core branch and not master (new file)
A       public/templates/dashboard.html          # Present in master and not in the core branch (don't touch)

So write a simple regex to select only the modified and new files and modify it to a proper format and then store it in a temporary file.

$ cat ~/.dummy

public/templates/createUser.html
public/stylesheets/main.css

Then we need to add those files to our current branch, so we use git checkout. See this answer for how to do so with git checkout.


There is another way to do this. The official way, using git rerere. From the man page:

In a workflow employing relatively long lived topic branches, the developer sometimes needs to resolve the same conflicts over and over again until the topic branches are done (either merged to the "release" branch, or sent out and accepted upstream).

This command assists the developer in this process by recording conflicted automerge results and corresponding hand resolve results on the initial manual merge, and applying previously recorded hand resolutions to their corresponding automerge results.

Note: You need to set the configuration variable rerere.enabled in order to enable this command.

This article gives a decent overview of the command and its use case.