#include <bits/stdc++.h>
using namespace std;
const int maxn = 400010;
map<int, int> q[maxn];
struct edge {
  int x, y, d;
  int ask;
} G[maxn << 1];
struct node {
  int x, y, d;
  int ty;
};
struct Tnode {
  int type, x, y;
  vector<node> g;
} g[maxn << 2];
struct Stnode {
  int re, x;
};
inline Stnode mn(int x, int re) {
  Stnode tmp;
  tmp.re = re;
  tmp.x = x;
  return tmp;
}
inline node mn1(int x, int y, int d) {
  node tmp;
  tmp.x = x;
  tmp.y = y;
  tmp.d = d;
  return tmp;
}
inline node mn1(int x, int y, int d, int ty) {
  node tmp;
  tmp.x = x;
  tmp.y = y;
  tmp.ty = ty;
  tmp.d = d;
  return tmp;
}
stack<Stnode> s;
struct bcj {
  int f[maxn], rk[maxn];
  int fad[maxn];
  int gf(int x) {
    while (x != f[x]) x = f[x];
    return f[x];
  }
  int get_dis(int x) {
    int res = 0;
    while (x != f[x]) res ^= fad[x], x = f[x];
    return res;
  }
  void add(int x, int y, int c) {
    int dx = get_dis(x), dy = get_dis(y);
    x = gf(x), y = gf(y);
    if (x == y) return;
    if (rk[x] > rk[y]) swap(x, y);
    s.push(mn(x, rk[x] == rk[y]));
    f[x] = y;
    fad[x] = c ^ dx ^ dy;
    rk[y] += rk[x] == rk[y];
  }
  bool check(int x, int y) {
    x = gf(x), y = gf(y);
    return x == y;
  }
} b;
struct xxj {
  int b[32];
  void ins(int x) {
    for (int i = 31; i >= 0; i--) {
      if (x & (1ll << i)) {
        if (b[i])
          x ^= b[i];
        else {
          b[i] = x;
          break;
        }
      }
    }
  }
  int gs(int x) {
    for (int i = 31; i >= 0; i--) {
      if ((x ^ b[i]) < x) x ^= b[i];
    }
    return x;
  }
} XD[32];
inline int ls(int x) { return x << 1; }
inline int rs(int x) { return x << 1 | 1; }
void ins(int p, int l, int r, int x, int y, node t) {
  if (x <= l && r <= y) {
    g[p].g.push_back(t);
    if (t.ty == 1) {
      g[p].type = 1;
    }
    if (l == r) {
      g[p].x = t.x;
      g[p].y = t.y;
    }
    return;
  }
  int mid = ((l + r) >> 1);
  if (x <= mid) ins(ls(p), l, mid, x, y, t);
  if (y > mid) ins(rs(p), mid + 1, r, x, y, t);
  return;
}
void dfs(int p, int l, int r, int dep) {
  int si = s.size();
  int i, j;
  for (i = 0; i < g[p].g.size(); i++) {
    if (g[p].g[i].ty) continue;
    int x = g[p].g[i].x, y = g[p].g[i].y, d = g[p].g[i].d;
    if (b.gf(x) == b.gf(y)) {
      XD[dep].ins(b.get_dis(x) ^ b.get_dis(y) ^ d);
    } else {
      b.add(x, y, d);
    }
  }
  if (l == r) {
    if (g[p].type) {
      int x = g[p].x, y = g[p].y;
      printf("%d\n", XD[dep].gs(b.get_dis(x) ^ b.get_dis(y)));
    }
    while (s.size() > si) {
      b.rk[b.f[s.top().x]] -= s.top().re;
      b.f[s.top().x] = s.top().x;
      s.pop();
    }
    return;
  }
  int mid = ((l + r) >> 1);
  XD[dep + 1] = XD[dep];
  dfs(ls(p), l, mid, dep + 1);
  XD[dep + 1] = XD[dep];
  dfs(rs(p), mid + 1, r, dep + 1);
  while (s.size() > si) {
    b.rk[b.f[s.top().x]] -= s.top().re;
    b.f[s.top().x] = s.top().x;
    s.pop();
  }
  return;
}
int n, m, Q;
int lt[maxn << 1], rt[maxn << 1];
int cnt;
int main() {
  scanf("%d%d", &n, &m);
  int i, j;
  for (i = 1; i <= m; i++) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    G[i].x = a;
    G[i].y = b;
    G[i].d = c;
    q[a][b] = i;
    q[b][a] = i;
    lt[i] = 1;
    rt[i] = -1;
    cnt += 1;
  }
  scanf("%d", &Q);
  for (i = 1; i <= Q; i++) {
    int act, x, y, d;
    scanf("%d%d%d", &act, &x, &y);
    switch (act) {
      case 1: {
        scanf("%d", &d);
        G[++cnt].x = x;
        G[cnt].y = y;
        G[cnt].d = d;
        lt[cnt] = cnt;
        rt[cnt] = -1;
        q[x][y] = cnt;
        q[y][x] = cnt;
        break;
      }
      case 2: {
        G[++cnt].ask = 3;
        rt[q[x][y]] = cnt;
        q[x][y] = q[y][x] = cnt;
        lt[cnt] = rt[cnt] = cnt;
        break;
      }
      case 3: {
        G[++cnt].ask = 1;
        G[cnt].x = x;
        G[cnt].y = y;
        lt[cnt] = rt[cnt] = cnt;
        break;
      }
    }
  }
  for (i = 1; i <= cnt; i++) {
    ins(1, 1, cnt + 1, lt[i], rt[i] == -1 ? cnt + 1 : rt[i],
        mn1(G[i].x, G[i].y, G[i].d, G[i].ask));
    b.f[i] = i;
  }
  dfs(1, 1, cnt + 1, 0);
  return 0;
}
